Introducing PyScript (summary of PyCon keynote)
lwn.net
lwn.net
But JavaScript vs Python isn’t really the key thing for me on the web. It’s the uncanny pile of other software one uses to build a man-machine connection that flummoxes me. It’s the CSS, the DOM, the events, the browser API, the ever churning massive pile of complexity that interactive software has become with the voluminous W3C specs, expressed in near BNF form and full of edge cases and backwards compatibility, all so every thing my user does can be observed by myself a few megacorps. I honestly wouldn’t care if I could write it in Fortran. It’s such a minor wart of the whole mess.
Caring about which actual language you can use in all the script tags of a jacked up text format feels like caring which font is being used in your favorite hot piece of government legislation.
- Annotating nested JSON objects is a pain in the ass. You need a bazillion intermediary classes.
- Sometimes you need a 3ish line lambda, because you have an beefy if-condition or a try-catch. Too bad multi-line lambdas aren't a thing.
- Function hoisting in JS is actually really nice, not just for the previous scenario. You can define utility functions at the bottom of a function and they'll be available to anything before that definition
- I wish python had a more succinct way to destructure dicts / objects like JS does, outside the new switch statements. (ie doesnt require imports, doesn't require typing the object name over and over.)
- Code completion doesn't work for list comprehensions because the for x in xs comes last :(
apply(lst, () => {
...
...
})
instead of def naming_is_hard():
...
...
apply(lst, naming_is_hard)I've had to deal with too much shit code where lambdas within lambdas are considered hot.
Added bonus, the names are useful (naming is hard because if you do it right you are adding valuable information).
I'm sure there are cases where doing it your way are better, but I can't think of them.
@apply(lst)
def naming_is_hard():
...
I came to python after working in JS fulltime for years, and used to complain about the exact same thing. After I started using decorators, I stopped complaining about the single-line lambdas.For any non-python devs looking at my example, it's equivalent to
def naming_is_hard():
...
naming_is_hard = apply(lst)(naming_is_hard)
It's a nice way to pass functions into other functions, much like how you'd do with a lambda.edit: s/list/lst/g because autocorrect "fixed" the variable name.
In all seriousness I do like them a lot. But like all things one can abuse them and make code unreadable.
Take Kotlin:
result = myList
.filter { it.myValue > 5 }
.groupBy { it.myKey }
.mapValues { entry -> entry.value.sumOf { it.myValue }}
In python: result = {
key: sum(el["myValue"] for el in elements)
for key, elements in groupby(
sorted([el for el in my_list if el["myValue"] > 5], key=lambda el: el["myKey"]),
key=lambda el: el["myKey"],
)
}
to me that's incomprehensible. You have to read it the wrong way, and it's not really clear what the intention behind each step is. Like, the filter is in the middle! keyOf = itemgetter("myKey")
valueOf = itemgetter("myValue")
filtered = (item for item in myList if valueOf(item) > 5)
grouped = groupby(sorted(filtered, key=keyOf), keyOf)
result = {key: sum(valueOf(item) for item in group) for key, group in grouped}From https://docs.python.org/3/tutorial/datastructures.html#id2
> You might have noticed that methods like insert, remove or sort that only modify the list have no return value printed – they return the default None. [1] This is a design principle for all mutable data structures in Python.
> Footnotes > [1] Other languages may return the mutated object, which allows method chaining, such as d->insert("a")->remove("b")->sort();.
Though personally I really like itertools and list comprehensions. (And list comprehensions are pretty functional as well, they were inspired by haskell I blieve.)
`import {foo} from ‘bar’;`
This makes reading code really really hard as I can’t tell where some symbol is coming from.
There also seems to be a general aversion against using classes to model types. Instead we have a host of functions that manipulate JSON/dataclasses, which means business logic is scattered around 10 different places!
That's why you use Typescript then you can just hover something or ctrl-click it.
Anyway Python is exactly the same in my experience. Sometimes people `import numpy as np` or whatever but most of the time they `from foo import X, y, z`.
I love JavaScript (yes, I'm one of THOSE people) and like what TypeScript brings to the table but it quickly becomes hard to read as the code becomes more complex.
Python has always had a readability advantage... up to the point where people start doing code golf and nesting multiple comprehensions together.
Can't really say that for most programming languages with the exception of Go.
What would you say it is about TypeScript that makes the code harder to read as it becomes more complex? Just the additional type annotation syntax, extra concepts like generics and/or the accompanying more exotic features of TS, the type definitions physically adding many lines of extra code, something about TypeScript that encourages code to be written in a certain way that is different and more complex?
Note that I haven't touched TS in about two years now, so my memory is a little fuzzy.
And yet the network effect would keep this going even if you had a team of a thousand brilliant people design a rational replacements for all of this ad-hoc cruft that has traditioned its way into being something like a standard.
Python is not a fast language. For example, consider a simple loop:
for i in range(10):
pass
In Python, this will be compiled into: a call to range(), heap allocation of an Iterable, calling getIterator() on an Iterable (which might also do allocation), calling next() on an Iterator while catching for StopIteration exception (and calls are often slow in interpreted languages). While in C we could just have a loop without any calls.I remember how I had to use a Dart-based web application (compiled to JS) in one of Google's advertising products. The script weighed around several megabytes and everything was so slow. Furthermore, there also was a small and useless "what's new" applet, and it probably was shipped with a separate copy of Dart runtime because it weighed several megabytes too. Obviously this was a product intended to be used only on latest MacBooks, not on a Windows XP laptop.
It is totally fine to write such application for youself, or maybe for internal use, but if you are a corporation with millions of users, I think you should pay a little attention to performance and choose a better technology. Or, if you are of a Google scale, find a way to optimize the code.
The incumbent is not C, it is JavaScript. Initially JavaScript was also simply run on an interpreter. And it wasn't particularly fast until it got considerable attention by Google & Co, and browsers competing for "who can run this silly JavaScript benchmark the fastest".
Then complaining about how more abstract languages like Python are inefficient compared to C is not fair. These calls to range and Exception handlers are there on purpose, to help the developer avoid writing boilerplate code for the millionth time, and focusing on the problem itself, writing cool things.
C would be a terrible language for the Web I would argue. Web "development" was never a thing for the greybeards and "I dream in assembler"-types (not that I want to exclude anyone, I mean it didn't attract that crowd and another instead). Any challenger for JavaScript must be approachable, easy to understand, easy to write and read. Easy to fix and modify (most "Web Apps" are already obsolete the moment they hit deployment).
Heck, why not go full x86 instructions? Hm, then there are millions of iPhones and Androids on the Web that are not x86... Write our own Assembler?! Let's call it WebAssembly!
Oh, wait.
For example, JS has no classes and uses prototype inheritance, and you can even change prototype at runtime. This is absolutely useless, inconvenient feature and it makes optimization (like JIT compilation) much more difficult (for example, before calling a method you must ensure that the prototype didn't change, the method was not replaced and so on).
In 95% (arbitrary number) of cases you just need classes with a fixed set of fields and methods known at compile time, which is very optimizer-friendly.
On the opposite: not only it isn't unfair, it's absolutely necessary. Over the years we witnessed the birth of so many languages, and each of them promised to be more safe than C while keeping performance "close to C". Now we have a cornucopia of programming languages, many of them are definitely "safer" than C (in the sense that it is more difficult or impossible to create some types of errors like buffer overflows), but in terms of performance there still seems to be a considerable gap. Having bad performance is bad for the users, bad for the environment (in terms of direct energy consumption and more power-hungry hardware needed), and bad for software companies (who are limited in what they can do).
Hacker News is written in some Lisp, and I spend more time here than on any bloated SPA.
Reddit with the old UI is a close second.
Also, C and Lisp are different breeds. It’s wrong to put them in one bucket of “greybeard” languages. Some Lisps gained traction in the front end space (see ClojureScript).
JS got fast because Google and friends started an arms race on it, since the adoption scale justified pouring resources into optimizing efforts.
Python has a large amount of developers' mindshare, which makes its use in the browser potentially worthwhile for large interests invested in the ecosystem (e.g. Anaconda). However, the problem is so big that the cost/benefit ratio for any given group that would want to tackle it, is still fundamentally unattractive. Python developers are legion, but still not a patch on JS users.
This is where WASM is a potential game-changer: by effectively dividing the problem in two and sharing the load for the first half with a lot of other ecosystems, the cost/benefit calculation improves significantly enough that commercial interests seem more willing to invest. CPython speeds, after the temporary v3 setback, get better and better every year; likewise WASM speeds. If their coupling becomes normal, enough effort will go into it that this consideration will just go away.
Also, it is unlikely that compiling to WASM will be more effective than to native code because browser cannot afford spending as much time on optimization as a native compiler. Therefore WASM will always be slower than a native code.
If you want to benefit from amazing optimizations that were done for JS, then it is better to transpile your Python code directly into JS.
No, but the bytecode gets better and more efficient with new releases. The point at which it becomes acceptable depends on the use case, of course.
> it is unlikely that compiling to WASM will be more effective than to native code
It doesn't have to be more effective, it only has to reach a point where the penalty is worth paying. After all, JS is slower than C, but you accept that as a part of larger trade-offs on manpower, ease of deployment, etc. Once the trade-off becomes acceptable for the use case, absolute benchmarks stop being relevant.
> If you want to benefit from amazing optimizations that were done for JS, then it is better to transpile your Python code directly into JS.
Why stop there? At that point you might as well use JS, since you get the best speeds and chances are you'll have to deal with it anyway at some point. There are already solutions like that out there, and they are not popular precisely for that reason. The beauty of using WASM is that you'll probably never have to touch JS.
No reason whatever compiles the code to wasm can’t perform all the expensive optimizations and the wasm execution environment just runs it.
In fact, I would be very disappointed in a tool that didn’t run optimization passes over the code while it still had the language specific information to inform the optimizer.
Then you just pass the multi-megabyte wasm payload over to the browser to render your static content — all’s still good in the webdev world.
[1] https://en.wikipedia.org/wiki/Dart_(programming_language)#Hi...
At this point the main issue I've seen is the slow load time (not a problem for jupyterlite but is for pyscript). Hopefully this can improve with time and regardless I think there are a lot of cases for pyscript to remove the need for server-side code and the associated maintaince.
We added support for PyScript using Collagraph, which allows you to define single file components with a Vue-like syntax.
Excerpt from the project README:
Write your Python interfaces in a declarative manner with plain render functions, component classes or even single-file components using Vue-like syntax, but with Python!
- Reactivity (made possible by leveraging observ)
- Function components
- Class components with local state and life-cycle methods/hooks
-Single-file components with Vue-like syntax (.cgx files)
- Custom renderers (PySide, pygfx and now PyScript)
Talking about optimizing a range(10) loop was valid in the 90's, not today
Yes, CPython could be better, but there's Pypy. And still, CPython runs circles around the optimized Dart example you gave.
"pay a little attention to performance" cool, are we going to take all the crap out of JS that makes it inefficient?
"pay a little attention to performance" sounds to me like you're a fan of those C compilers that break code on purpose because the developer forgot some arcane detail. To what I call BS
Of course if you are writing an internal app and can provide M2 MacBook to every employee, then it is totally fine. But if you are writing applications for wide audience, it is a different thing.
I remember that one of early users of Vkontakte (a Russian clone of Facebook) was impressed that the site was loading fast on his old computer. As I remember, its JS code was written in vanilla JS without libraries like jQuery. Today the hardware is better, but if you will run SQLAlchemy in a browser to save development cost, your site's loading time won't impress users.
> your site's loading time won't impress users.
Anybody who used client-server apps in the 80s and 90s is not impressed by browser-based apps either. Those expectations can be managed in so many ways.
Yes that will be a complete non starter!
I'm all for fighting inefficiencies and slow code, but fixing things like this, or Redux etc go much further than a simple for i in range() loop in Python
Anything written to be performant is immediately noticeable - things just happen when you click a button. Dev time > runtime, but I’d argue some runtimes are so slow they begin to eat into user time too.
I can only imagine how many people will just close the tab and move to next search result.
> But there is another aspect of the language that makes it so desirable from his standpoint: it can be extended with binary extensions that use an API that is written in C, but can be accessed from other languages. He likens Python to "a Honda Civic with mounting bolts for a warp drive". So the language can be picked up by kids who can then pop open the trunk "and bolt on warp nacelles" that allows the code to run faster than C or C++ in some cases, Wang said.
>
> That aspect is sometimes overlooked, but it means that Python can be used in ways that other, similar languages cannot. "It's not just like Node, it's not just an alternative to Ruby".
Both node and Ruby have a comprehensive C API, this is a very common language feature since binding to native libraries is unavoidable. Is there actually anything different about python here?https://nodejs.org/api/n-api.html https://silverhammermba.github.io/emberb/c/
I say this as a big fan of Python: I think the main difference is that the CPython C APIs are much more of a pain to use :-)
I don't know about Node's C APIs, but I've written both Python and Ruby extensions and find the MRI APIs much nicer than the CPython ones.
Iterator support is a little trickier but not too bad once you have it figured out. Same with overloaded functions. Array access is a bit annoying because there’s two ways to do it and you have to guess the right one if you want slices and other craziness.
Memory management can be a pain but I’d imagine it is like that whenever you’re combining two languages.
I’ve done some pretty complex wrappers and have yet to find something that just isn’t possible (within the limitations of python). I usually get the boilerplate generated from pybindgen and then start on the serious hacking.
Actually… I did find something that wasn’t possible and that was because someone thought it was a good idea to commit the raw buffer interface (whatever it’s called) before it was finished and I wasted a whole lot of time on that before I dug into the python source to figure out why it wasn’t working.
But neither of these implies that the CPython API is exceptionally good: (1) can be an overriding factor during the implementation of (2), and (2) means that the average scientific Python user doesn't actually need to touch the CPython APIs that much (all the work is already done!).
So I don't think my feedback ("Ruby extensions are easier to write than CPython extensions") is actually incongruous with the rest of the world; the rest of the world picked Python because it's a better language in the ways that matter.
Edit: Well, maybe 20 years ago -- 10 years ago, Ruby's C API was about the same and still (IMO) better.
I think the key point here is that Python prioritized making native add-ons easy, and so it actually developed an ecosystem. The very second sentence on Ruby's C API that is linked above says "the API is huge and largely undocumented."
JS could sort of probably do most things Python can, except for there not being a huge effort for JS things to be native binary (compiling an exe wrapper that executes a VM is not the same thing, e.g. electron). I know there are various C++ injected JS dependencies on node...
Python has a distinct advantage of being a bit closer to the metal, though. Yeah the default python intepreter yadayada - but that's the honda civic bit. You can compile python to c code, compile it, and _call random python modules from within your c code_ all automatically. Or generate a binary c module, or create or a fully compiled exe, or create a python app with an embedded vm, or run the whole thing in a JIT....there's a lot of flexibility.
"Oh but with package XYZ I can cobble together something similar in JS" - yeah, you probably can, but normally you have to contend with a browser, or modules written for a browser, or a DOM, or a transpiler/webmaplicabroominator (don't ask, there's some real nonsense in the JS space) - its all non-standard, plus most of it has only existed for <5 years, python land has had this for...decades now?
JS is what you get when you build a language around a DOM, don't get me wrong, it can do some nifty things. Python is what you get when you mostly don't care about fancy UI...
I suspect Ruby is in a closer boat to Python than JS, but, python has been a more perlesque language insofar as its use as a glue language, Ruby is/was definitely focused on being a fantastic web rendering language (with a bit of JS UI glue). This is evident where python is often used - you can normally get a python binding, even if you don't have a JS or ruby binding.
Again, not the world - as far as type safety there are much better alternatives than any of these, for systems or reliability I would not depend on python (alone).
I'm not a C developer, so for me if the question is, can I call out to a C module that implements capability X, the answer to that is much more likely to be yes for Python than it is for Ruby.
Ruby has had Fiddle[1] (a libffi binding) in stdlib for a while now. I don't know when exactly they added it, but it's been at least a couple of years.
Edit: I gave a talk on obfuscation in Ruby that used Fiddle back in 2017, so at least 5 years now.
Edit: But I also don't think that's what the speaker meant. "Binary extensions" are a semi-standard concept in Python, and generally refer to code (modules or packages) that gets compiled against the Python C APIs.
[1]: https://ruby-doc.org/stdlib-3.1.2/libdoc/fiddle/rdoc/Fiddle....
In ruby 1.9.2 [0], released in 2010.
> But I also don’t think that’s what the speaker meant. “Binary extensions” are a semi-standard concept in Python, and generally refer to code (modules or packages) that gets compiled against the Python C APIs.
Ruby has the same thing.
[0] Based on when it first appears in the standard library documentation on the web; 1.9.1 doesn’t have it, 1.9.2 does.
Re edit 2: I've made those sorts of binary extensions before, but his wording is "extended with binary extensions that use an API that is written in C, but can be accessed from other languages", implying it's actually just about loading libraries with C ABI and not ordinary binary modules, at least by my interpretation.
If I'm going to be bound by the limitations of how immature WebAssembly is right now, I'd at least use its more mature ecosystem for development, which is Rust. And actually, I recently began doing so in my free time with a framework named Yew[1].
I know that it's unrealistic to expect Python to be a first-class citizen in browsers as JS is, but at some point we'll grow tired of reading "X language is now available for browsers" when it's more like "X can do WASM now".
edit: Anyway, I don't want to come off as under-appreciative of PyScript. I'm sure a lot of people will love it and make it grow a lot. I'd probably give it a try someday too. Props to the developers!
That you have to ship the entire interpreter isn't great, but what it means for development is that there is no compilation step. You don't have to deal with the WASM toolchain directly. You write your Python code, refresh the tab, and see the results. That's a huge step up from trying to use Rust and WASM for the majority of people who aren't yet Rust developers.
Obviously it's super immature at this stage, but the future possibilities are exciting.
Doing it inside a custom element like <py-script>…</py-script> has been done occasionally, but doesn’t work well because (a) the code is now visible in the document by default and only hidden by stylesheets, and (b) < and & now need to be escaped as < and &.
This is something I find common in the Python ecosystem. There seem to be a lot of choices made more for the benefit of the developers than the end users. Even getting a Python app with some idiosyncratic build system to run can be a challenge sometimes.
Lua in the browser: https://fengari.io/
And then you can use that to run Fennel, a Lisp that compiles to Lua https://fennel-lang.org/
I think TypeScript also has a script you can include that lets you put your TS code in a special script tag, and it gets compiled in-browser.
> For example, you cannot write iOS apps with Python. You cannot create an application for Windows—the most popular corporate desktop—with a user interface
You can, in fact, do both of those things with Python. Heck, the latter you can do with the standard library alone.
The problem is that packaging a PyQt project is too difficult.
PySide is more permissive though (LGPL).
On Windows you can generate a folder with a bunch of files in it along an .exe that starts your app pretty easily and that'll work in most places just fine and is not excessively large, either.
That said, it has really brought out the knee-jerked clichéd responses:
- X is way better than Y
- X is the Y killer / no it isn't
- Did you know Python is really slow?
- Sure you can, but why do this? (implication: don't do this)
To add to the fun, it attracts huge interest, and amongst those interested are a weird set of people who seem to know little about Python, little about JavaScript and seem unable to read before they try something impossible and then post a query about why their almost certainly never-going-to-work attempt hasn't worked! It needs plenty of patience pointing them to the huge pile of matching queries! I'm sure something will be done to give those types a friendly nudge in the right direction.
In my experience, it's trivial accomplish this with Pyodide.
Here's a web worker that hosts Pyodide and loads packages, PyPI wheels, external modules, etc. and launches type=text/python script tags in-browser:
https://github.com/h2oai/nitro/blob/main/web/public/nitride....
About ~100 lines of code.
const
pyodide = await loadPyodide(),
input = document.getElementById('#input').textContent,
output = await pyodide.runPythonAsync(input);
document.getElementById('#output').textContent = output;
I can see there are other tags (py-env, etc.) that provide some yaml to fetch additional assets, but again, nothing significant that warrants the hype.Maybe I'm missing something?
I used to love Python's list comprehensions etc, but since JS got .map, .filter, and all the other new things I really don't miss them. My impression of async is that it's much nicer in JS than in Python.
In the new version of my employer's web app we are moving from JS front-end with Python (Flask) backend to using as much Typescript as possible, and only using Python where we need data-sciency / ML libraries. We'll call out to it from our Typecript backend as-needed, but will do as little in Python (and especially in Pandas) as possible.
TypeScript is just a terrific choice for basically any web SPA. My current company is full stack TS (React/TS/MobX on the web, React Native/TS/MobX on mobile, RESTful Express/TS/Postgres/Redis services), and it’s the most productive, straightforward stack I’ve ever used. Perfectly decent performance too. A single language that is legitimately a great choice for most use cases on the web, mobile and backend, hard to compete with that.
The biggest efficiency gains, though, are:
- Much faster training/ramp up time for new devs with TS vs Scala
- You can use the same language on the FE and BE, makes it easier for individual devs to do full stack work
The main downsides of TS vs Scala are:
- Scala is faster and more efficient, performance wise. Have to spend more on TS services to serve the same amount of traffic, and if you have heavy computation that’s parallelizeable, Scala is wayyyyy better at that
- As you get into more niche use cases, you just can’t beat the JVM library ecosystem, there are high quality libraries for EVERYTHING. The Node ecosystem is very good too, but not as good as the JVM ecosystem
- TS/Node stack traces are useless compared to Scala/JVM stack traces
Overall, I’ve got ~7 years of professional Scala experience, love the language, but if I was starting a startup today, I’d go full stack TypeScript.
For me, the context switch between client and server was always difficult using a Scala/TypeScript setup (startup).
As you said, unless you rely on some niche technology only available on the JVM, it‘s probably more productive to go full stack TypeScript. For perf-heavy workloads I would probably pick Rust instead of Scala.
It's a little hard to describe how magical it feels to actually use. It completely removes needing to think about an API. You don't think about endpoints, about (de)serialization, about the mechanics of fetching, or how arguments are passed. You just call you functions by name from the front-end. All your types are preserved so that if you change the signature of your backend function Typescript will catch it everywhere on front-end. If you use react-hook-form then you can export the zod validators that you wrote for the backend and import them to the frontend, and now your client-side code is using the exact same validator as your backend does. Change your server side validation and now your client-side form won't compile and you'll know exactly why.
Honestly it feels like the missing link in fullstack dev to me. Typescript brought the types and the compiler, and tRPC makes it feel like your entire back and front-end are one system.
I will definitely give it a go, thanks.
Unfortunately Javascript makes you do almost everything async, no choices. Which makes you think that way. Which is awkward to start with and can lead to a lot of strange corner cases. In python unless you're really trying to squeeze performance out of a system you almost never need async.
I guess it could be that they just don't care about this type of thing to begin with and have no idea why they are using async other than they heard "it is faster". Meanwhile I am pulling my hair out trying to squeeze a more reqs/s out of an on premise server.
although i really do love javascript's ability to await synchronous functions without it causing any errors. i'm sure it's less performant, but sometimes i just don't care.
I'm saying this as someone who has been programming in many languages since more than 20 years.
if (sth)
sth1();
sth2();In my experience, there's no syntax that would be free of gotchas and pain points - I tend to accept them, and if I'm going to work with a particular syntax more than once, I write a bit Elisp to make working around them as seamless as possible.
This alone makes it deserve its existence and further pursuit (“for the other 99%”).
Imagine a world where only mechanics could drive cars, because the way they worked “would be fine with him or her” but for everyone else there would be a steep learning curve to overcome initially - which most won’t embark on because there are other goals in life too.
Keeping with the analogy, normal cars are still not suited for Grand Prix racing or other heavy use cases. But this is not needed for the 99%.
Its the same with Python, its limitations, and the better suitability of other languages for a mix of specialised and performance use cases.
I think it would be great if more people would be able to create web applications, but there should be better technologies than shipping a ten-megabytes interpreter with every HTML page.
Also Python is not easy for non-developers. It might be easy for middle school level tasks like replacing a word in a string. However if you want to use a database, you have to learn about object-oriented programming, property descriptors, ORM and decorators, all of these are difficult topics and libraries like SQLAlchemy are not for beginners (just look at its documentation. It doesn't even explain what ORM means).
Javascript is everywhere on every device with a browser - if you can load a web page, you can start coding in javascript right away. No install needed - you have a REPL right in your browser.
Granted, NPM is a mess but that is not mandatory and it is still perfectly possible to write & ship modern production JS code without NPM or build-steps being involved. Modern JS is very powerful, and if you can stomach a build-step TS makes it even better.
You basically need NPM if you want to work with any kind of libraries, and I'd say the Anaconda system comes with way more ergonomics out of the box, so that's more or less a wash.
A closer metaphor is: imagine a world where everybody builds their own car. That would be a bit of a mess.
15 requests. 21.65 MB / 7.66 MB transferred. Finish: 8.19 s. DOMContentLoaded: 707 ms. load: 2.95 s.
no, stop. I'm super confused about the obsession of clonking specifically the reference implementation when other implementations exist, like micropython for example. Sure, less compatible, but you are already not getting native modules so shrug?
IIUC, the TLDR is that they're experimenting with loading a bunch of popular scripts (e.g. top `N` scripts from CDNs) on all browsers, so the response is immediate, but they can't use the timing for fingerprinting because it's immediate for everyone.
Loading the entire wasm, touching all the things that need to be touched, etc, takes up the majority of the time
Unfortunately https://www.npmjs.com/package/micropython is three years unmaintained.
Runtime offset of Hello World matters a lot less if you do real python stuff: physics, neural networks etc
https://webassembly.org/docs/security/ https://www.reddit.com/r/WebAssembly/comments/ryz2zz/are_was...
Deno also touts its permission system. It will be interesting to see if both get interesting use.
micropip is impressive. A lot of JavaScript dev still depends heavily on Node, to the point that only one browser-based build tool exists that can handle most projects and they're keeping it proprietary: https://blog.stackblitz.com/posts/introducing-webcontainers/
It's great for shipping small, internal tools/apps, I love how maintainable they are by all the Python devs, plus they're very fast to load and execute.
I did a writeup with a basic how-to a while back: https://dev.to/jennasys/creating-react-applications-with-pyt...
Brython uses:
<script type="text/python">
[0] https://brython.info/* Slow start up times (a second or half a second) for anything that includes the python standard library.
* Avoiding the standard library means writing javascript helper functions so you end up needing to know and write javascript anyway. In some ways Brython feels like "Python for javascript programmers"
* Integration with browser for error messages isn't as convenient as for javascript where I can "click into" the js file in dev tools.
* Pierre is brilliant but it is clear that it is a labor of love. He doesn't want corporate sponsorship or anything that would make it a job for him. He works tirelessly on Brython, the man is a machine, but it really is just him having fun. What happens when its not fun any more? There is no obvious succession. The lack of corporate sponsorship/marketing means that the community is small, there's no "virtuous cycle" of adoption.
I hope the above doesn't mis-represent Pierre, this is my perception only.
Lastly, in recent years many people came to python for the scientific/ML libraries which don't work with Brython. To these people, a python without numpy is no python at all?
UPD: I looked at the compiled code and currently it is unlikely to be optimized. Also this page [1] shows that the code run in browser can be up to 1000 times slower than in a native Python interpreter.
I will also point out that there is some fairly low hanging fruit in this PyScript project, if they will attempt to be more "web native". Take this example: https://pyscript.net/examples/panel_kmeans.html
It loads a bunch of large `.whl` files, and they're served up without any apparent compression, which raised my eyebrows immediately. Upon closer inspection, this is a zip file under the hood, so they probably figured that compressing a zip file over the wire was a waste of resources, and they're not really wrong... but, does it need to be a zip file? That means they're shipping a library to handle decompressing and manipulating zip files.
If we unpack the zip file and make an uncompressed tarball out of it, we can feed that through brotli and get a much smaller file:
18M bokeh.whl
9M bokeh.tar.br
The network transfer is now twice as fast, and the browser will do a phenomenal job at decompressing this resource before handing it to the application. The browser will (presumably?) decompress these resources in parallel instead of the (likely) sequential process currently being used, the browser should be faster at decompression anyways, and not handling decompression means less code that PyScript has to ship. Even better, subsequent page loads wouldn't have to keep decompressing the same bundle over and over... it'll just be a cached resource. You'd still need to handle the tar format, but that shouldn't be too terrible.Basically all browsers support Brotli[0], and you could always have a slow fallback for the... checks notes... IE 11 users out there.
This kind of low hanging fruit won't magically fix all the problems with PyScript, but it could go some distance towards making it more palatable for the purpose of bundling up a lightly modified Python application for use over the web.
Still waiting for Windows Platform to become Universal.
ActivePython was available via the <object /> tag for Internet Explorer back in the early 2000's.
https://pyscript.net/examples/d3.html
The python version is much much slower loading at least on my browser. I counted 7 seconds to having it render the graph.
I kinda wish they spent the time thinking about Dom manipulation from a pythonic point of view rather than just providing the python to js interface and calling it a day.
Python (the spec) is not against a JIT. Only CPython (the interpreter) is, which is a reference implementation. Other implementations such as PyPy use JIT. I guess Jython can also use the JIT features of the underlying JVM.
The IR is also a lot less opinionated than other VMs. It started out being similar to a stripped-down JavaScript in capability, but broadened. At the same time it remained easy for browser engines to process into native code. Compared to optimizing applets, it has a simpler task to solve. This does have the disadvantage that modules need to come with their own runtimes. Compilers for languages like C have to deal with the fact that their host languages expect to be running on a fully-featured OS instead of a browser.
Even though it is a binary blob downloaded over the web, browsers come with disassemblers that allow you to see what is actually running. This is a step up over applets, but this is one part of WASM I find particularly underwhelming. The messy development of the VM affected the text format the most, so it's more confusing than it really needs to be. Some docs expect you to write it like a Lisp, even though there's no parse tree encoded in WASM.
WASM has quite a few problems, but they're at least different problems than the ones applets had.
1. https://github.com/WebAssembly/design/blob/a19e4ccf9c250cc73...
But I see the similarity in terms of compiling your software down to another (supposedly universal, we’ll see) intermediate instruction set.
For example, I'm one of developers of Gradio [0], which lets you write your web app in Python, which gets rendered using Svelte-based components:
Sure, there are lots of things that do that.
They don't let you build apps using the Python scientific stack that live entirely in the browser, because they tend to be transpilers plus implementations of a subset of the stdlib plus some browser-specific libraries, whereas PyScript bundles WASM-compiled versions of important Python ecosystem libraries.
They have different strengths.
But since it's kind of niche among the rest of JS frameworks, I'm wondering, what made you chose it over the alternatives?
Meanwhile, JavaScript has been extended with so many language features that it's hard to see another scripting language giving people good reasons to switch. In the early days, JavaScript programming was very limiting and alternatives had a chance, but those days are pretty much over and I'd recommend just learning JavaScript.
(I say this as someone who spent more time exploring alternative languages than writing JavaScript by hand. Nowadays it's hard to come up with a good reason to bother.)
I also contribute to Wave[2], which provides a wide variety of widgets that can be snapped together quickly to build realtime dashboards/apps.
Both help non-front-end folks build web apps, and require no knowledge of HTML/JS/CSS.
* Panda3D's main language is Python
* Godot has Python bindings
* So does raylib
...
Maybe it is sad, but it’s definitely the shortest path to brining modern frontend dev to Python.
We wrote our findings of this and many other libraries here: https://news.hal9.com/posts/data-science-with-javascript
Feel free to check out our repo as well, all the "primitives" / blocks code is in the scripts folder: https://github.com/hal9ai/hal9ai
I slowly started making more JavaScript stuff and used Selenium (python IIRC).
Then I started learning node. Liked npm's default to local project installs vs python's default to system installs. Eventually I started writing the command line tools that I'd have written in python previously in node. node had some sync I/O so it wasn't hard. Then promise/async/await arrived and I was fully in. I haven't written much python in probably 9 years now.
When I do look at python, I don't feel it's better. I'm not saying it's worse nor am I saying it's not better, rather I'm saying it doesn't *feel* better. Basically I've learned JS inside and out and I'm super comfortable there.
I find it easier to get node installed on multiple platforms and installing it locally without root/admin privileges is trivial via nvm. I'm sure that's possible with python but it's certainly not the default. And of course the browser is everywhere so it's just way more accessible/sharable in JS
May as well write Javascript directly, as NPM is not short on packages if that's what you need. I see more value in going from higher level languages like ReScript, Purescript, Melange (Reasonml + Rescript compiler) to Javascript. You have to deal with things like code interop, strictness, overhead of compilation, but you at least gain in safety and succinctness.
I haven't heard of an equivalent of the Python scientific stack for JS, and that seems to be one of the key selling points here.
All web API docs are written for Javascript. Knowledge and practice of Javascript is mandatory for front end development at first place.
https://pwhiddy.github.io/more-writing/2022/05/05/Pyscript-T...
How do they do it? The whole point of numpy and pandas stuff is that they are Fortran and C code that does numeric operations very quickly, while the Python part gives a nice and ergonomic interface on top of them.
So they are showing a WASM port of NumPy / Pandas now, with the Python interface finally surfacing in the browser. It should be a very fair bit slower than native code, though.
Are we seeing the Atwood Law stumbling? That is, things are still migrating into the browser, but to WASM instead of JS now?
[Brython]: https://www.brython.info/
What? No one mentioned Rust or Go.
(slowly heads for the exit)
It should at this point be enshrined as an official binding standard that browser UAs must support JS and must NOT support any other scripting languages