|
(Disclosure: I'm a maintainer of https://skulpt.org, another Python-in-the-browser runtime, as well as a Python web framework/dev environment that uses it, https://anvil.works) The short answer is that basically all the current Python-in-the-browser implementations (and there are a few!) predate widespread support of WASM. But even once WASM is a thing, you get a choice between: 1. Compile a full Python environment to WASM (via Emscripten), and load it in the browser. This is what Pyodide does - it lets you use a boatload of existing libraries, but you have to download and bytecode-compile the world to do it. On my machine Pyodide takes 10+ seconds to load. (PyPy.js, which predated WASM, was even worse!) The upside is that you can run more or less anything from the existing ecosystem. This tradeoff is great for Pyodide's use case (notebooks in the browser) - long load times are OK, but you really want those numerical libraries. 2. Ship a lightweight, JS-based runtime. This is what Brython and Skulpt do. You'll pay in performance (compilation overhead, interpretation, and the overhead of preserving Python rather than JS semantics for things like attribute lookup), but your payload will be much smaller (Skulpt is ~250kb on the wire), and you'll be interactive much faster. We chose Skulpt for the client side of our full-stack Python-in-the browser platform, Anvil (https://anvil.works). Unfortunately, you'll be amazed how many Python libraries don't work in this environment. Most "normal" Python code is pretty straightforward, but dig into any big library and you'll find a native dependency really fast. (Skulpt's original 'datetime' implementation was ported from PyPy, and even that depended on native code. In PyPy, the interpreter written in nearly pure Python!) In something like Anvil, this is no biggie, because you can call server-side code with one function call, but it could be a nasty surprise in a traditional app. 3. Compile "not quite Python" to JS (this is what Transcrypt does). This more or less transliterates Python code to the nearest Javascript equivalent. This produces really compact, JIT-friendly JS code, but it will bite you the moment you rely on Python semantics that aren't there in JS. Worse, you're now neither fish nor fowl: If you have a question, you can't consult StackOverflow for Javascript answers, but half the Python answers won't work for you. (To my knowledge, nobody has yet attempted the "WASM + lightweight runtime" approach. We've occasionally discussed it, but it would be hard to retrofit to an existing project, because you'd want to move a-lot-but-not-all of the runtime into WASM to avoid being hammered by the JS-WASM bridge, and building a Python runtime from scratch is a heavy lift...all for a performance boost you might just get from generating faster JS.) Before the pandemic, a colleague of mine wrote an in-depth comparison of six popular Python-in-the-browser implementations, with sample code and a discussion of their trade-offs, with a lot more detail than I can fit into this comment: https://anvil.works/blog/python-in-the-browser-talk |
MicroPython has a version working in the browser using unicorn.js (which emulates ARM CPU). [3]
[1] https://micropython.org/ [2] https://sneklang.org/ [3] https://micropython.org/unicorn/