Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Python 3.11 in the web browser – A journey (PyCon DE 2022 Keynote)

Python 3.11 in the web browser – A journey (PyCon DE 2022 Keynote)

https://2022.pycon.de/program/SBCNDY/

Python is ubiquitous, popular and runs almost everywhere – even on Mars. But there is one place that Python has not yet conquered: the browser. Python 3.11 may finally lay the foundation to make an old dream come true and have Python in the web browser.

In my talk I will explain how to cross-compile CPython 3.11 to Web Assembly and demonstrate how to run CPython in JavaScript engines. The talk will cover

- Why are some core developers and contributors working on Web Assembly port?
- What is WASM and how do builds for browser, node, and WASI differ? What are the features and limitations of different WASM targets?
- A short introduction to Python’s build system and how cross compiling works.
-What problems did we run into and how did we have to modify CPython’s sources for WASM?
-What is missing to make web browser support stable and usable in production?
- A comparison to existing solutions like Pyodide.
- What does WASM support mean for the community and PyPI packages?

Christian Heimes

April 13, 2022
Tweet

More Decks by Christian Heimes

Other Decks in Programming

Transcript

  1. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    PyCon DE 2022 Keynote Python 3.11 in the web browser – A journey Christian Heimes Principal Software Engineer [email protected] [email protected] 1 @ChristianHeimes
  2. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    3 I have a confession to make… ▸ I have no experience with front-end development. ▸ I don't know how browsers work. ▸ I never learnt JavaScript. ▸ I started learning WASM a couple of months ago.
  3. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Python 3.11 in the web browser – A Journey 4 C WebAssembly bleeding edge
  4. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    5 How to run Python code in the browser? ▸ Execute Python code on the server ▸ Create Python interpreter in JavaScript ▸ Transpile Python code to JavaScript code Brython, source-to-source translation ▸ Browser plugin Netscape Plugin API (NPAPI), ActiveX, Google NaCl Pepper, … Adobe Flash ▸ Compile to WebAssembly
  5. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Katie Bell: How to run Python in the browser 6 Linux Conf AU 2022 ▸ 10 min: introduction ▸ 2 min: (compile and) run Python in the browser ▸ 28 min: making stdin work (keyboard input)
  6. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    8 How it's going 2022-04-05 / 2022-03-21 $ node --experimental-wasm-threads \ --experimental-wasm-bulk-memory \ python.js -m test -w == CPython 3.11.0a7+ (heads/bpo-40280-smaller-build-dirty:eb79f02293d, Apr 8 2022, 10:58:59) [Clang 15.0.0 (https://github.com/llvm/llvm-project 80ec0ebfdc5692a58e0832125f2c == Emscripten-1.0-wasm32-32bit little-endian == cwd: /python-wasm/cpython/builddir/emscripten-node/build/test_pyt hon_42æ == CPU count: 8 == encodings: locale=UTF-8, FS=utf-8 0:00:00 load avg: 0.10 Run tests sequentially 0:00:00 load avg: 0.10 [ 1/435] test_grammar 0:00:00 load avg: 0.10 [ 2/435] test_opcodes ... == Tests result: SUCCESS == 342 tests OK. 92 tests skipped. Total duration: 12 min 22 sec Tests result: SUCCESS
  7. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    9 Contributors ▸ Ethan Smith, Brett Cannon (python-wasm) ▸ Erlend Aasland (build system) ▸ Katie Bell (browser UI) ▸ Hood Chatham, Roman Yurchak (Pyodide) ▸ Sam Clegg, Thomas Balling (Emscripten) ▸ Paul m. p. P., Trey Hunner (early adopters) ▸ Lin Clark, Dan Callahan, David Beazley (talks) ▸ … and many more
  8. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    WebAssembly compilers operating systems 10
  9. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    caniuse.com/wasm ? 11 Modern browsers support two programming languages Wasmer wasmtime Node
  10. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    12 Compilers human code to native machine code C C++ Go Rust frontend frontend frontend frontend intermediate representation backend backend backend backend x86_64 i686 aarch64 armv7
  11. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    13 def line(a, x, b): return a * x + b double line(double a, double x, double b) { return a * x + b; } # elf64-x86-64 0: f2 0f 59 c1 mulsd xmm0,xmm1 4: f2 0f 58 c2 addsd xmm0,xmm2 8: c3 ret # elf32-littlearm 0: ee002b01 vmla.f64 d2, d0, d1 4: eeb00b42 vmov.f64 d0, d2 8: e12fff1e bx lr # elf64-s390 0: b3 1c 00 02 mdbr %f0,%f2 4: b3 1a 00 04 adbr %f0,%f4 8: 07 fe br %r14 a: 07 07 nopr %r7 c: 07 07 nopr %r7 e: 07 07 nopr %r7 Instruction Set Architecture (ISA) gcc -O2, objdump -d
  12. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    14 # line(a=3, x=5, b=2) local_vars = (3, 5, 2) def get_local(idx): push(local_vars[idx]) stack = [] push = stack.append pop = stack.pop def add(): right = pop() left = pop() result = left + right push(result) code = [ (get_local, 0), # load a=3 (get_local, 1), # load x=5 (mul,), # store 3*5 (get_local, 2), # load b=2 (add,), # store 15+2 ] Stack machine def mul(): right = pop() left = pop() result = left * right push(result) for instr, *args in code: instr(*args) result = pop() # 17
  13. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    15 # WASM text (WAT) (module (export "line" (func $line)) (func $line (param $a f64) (param $x f64) (param $b f64) (result f64) get_local $a get_local $x f64.mul get_local $b f64.add ) ) WebAssembly Text (WAT) >>> import dis >>> def line(a, x, b): ... return a * x + b ... >>> dis.dis(line) 2 0 LOAD_FAST 0 (a) 2 LOAD_FAST 1 (x) 4 BINARY_MULTIPLY 6 LOAD_FAST 2 (b) 8 BINARY_ADD 10 RETURN_VALUE BINARY_OP_MULTIPLY_FLOAT BINARY_OP_ADD_FLOAT
  14. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    16 Compilers human code to native machine code C C++ Go Rust frontend frontend frontend frontend intermediate representation backend backend backend backend x86_64 i686 aarch64 armv7 backend wasm32 Emscripten SDK
  15. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Opening a file on disk 17 open("file.txt") _io.TextIOWrapper _io.BufferedReader _io.FileIO // _io/fileio.c #include <fcntl.h> int fd = open( path, flags, ... ); glibc libc.so.6 open(path, ...); openat( dirfd, path, ... ); syscall( SYS_openat, dirfd, path, ... ); open Kernel sys_call_table ... VFS ext4fs block device SATA ... syscall
  16. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    18 Problems ▸ Linux, macOS, Windows, … have different APIs ▸ Linux syscall numbers are arch-specific x86_64: 257, i686: 295, ARM: 332, aarch64: 56, ... ▸ Browsers are sandboxed How to open a file safely on all platforms? (import "env" "__syscall_openat" (func $fimport$1 (param i32 i32 i32 i32) (result i32))) (import "wasi_snapshot_preview1" "fd_read" (func $fimport$2 (param i32 i32 i32 i32) (result i32))) (import "wasi_snapshot_preview1" "fd_close" (func $fimport$0 (param i32) (result i32)))
  17. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Opening a file on Emscripten / WASI 19 open("file.txt") _io.TextIOWrapper _io.BufferedReader _io.FileIO // _io/fileio.c #include <fcntl.h> int fd = open( path, flags, ... ); musl static libc.a open(path, ...); openat( dirfd, path, ... ); syscall( SYS_openat, dirfd, path, ... ); open Browser NodeJS WASM import / export WASI runtime MEMFS NODE raw FS
  18. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    20 JavaScript "Kernel code" Emscripten's glue layer var asmLibraryArg = { "__syscall_openat": ___syscall_openat, "fd_close": _fd_close, "fd_read": _fd_read }; var info = { 'env': asmLibraryArg, 'wasi_snapshot_preview1': asmLibraryArg, }; WebAssembly.instantiate(binary, info); function ___syscall_openat(dirfd, path, flags, varargs) { SYSCALLS.varargs = varargs; try { path = SYSCALLS.getStr(path); path = SYSCALLS.calculateAt(dirfd, path); var mode = varargs ? SYSCALLS.get() : 0; return FS.open(path, flags, mode).fd; } catch (e) { if (typeof FS == 'undefined' || !(e instanceof FS.ErrnoError)) throw e; return -e.errno; }
  19. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    21 ▸ x86_64-unknown-linux-gnu ▸ x86_64-unknown-linux-musl ▸ armv7l-unknown-linux-gnueabihf ▸ aarch64-unknown-linux-android ▸ aarch64-apple-darwin ▸ i686-pc-windows-msvc ▸ sparcv9-sun-solaris ▸ wasm32-emscripten ▸ wasm32-wasi Target Triple(t) machine vendor os (abi) "CPU" "OS"
  20. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    22 What is WebAssembly ▸ "machine-independent machine code" ▸ binary (.wasm), text (.wat) with metadata ▸ designed to be portable and fast ▸ 4 value types (integer i32, i64; float f32, f64) ▸ ~200 instructions ▸ optional extension (128 bits vector ops, threading) ▸ wasm modules have ・ imports ・ exports ・ memory
  21. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    24 ./configure && make Autotools and Makefile $ ./configure checking for git... found checking build system type... x86_64-pc-linux-gnu checking host system type... x86_64-pc-linux-gnu checking for Python interpreter freezing... ./_bootstrap_python checking for python3.11... python3.11 checking Python for regen version... Python 3.11.0a6 checking for pkg-config... /usr/bin/pkg-config checking pkg-config is at least version 0.9.0... yes checking for --enable-universalsdk... no checking for --with-universal-archs... no checking MACHDEP... "linux" checking for gcc... gcc ... $ make gcc -c -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -std=c99 -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Werror=implicit-function-declaration -fvisibility=hidden -I./Include/internal -I. -I./Include -DPy_BUILD_CORE -o Programs/python.o ./Programs/python.c ... CC='gcc' LDSHARED='gcc -shared' OPT='-DNDEBUG -g -fwrapv -O3 -Wall' ./python -E ./setup.py build running build running build_ext ...
  22. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    configure 25 autoconf, m4 ▸ feature detection ・ compiler settings ・ platform settings ・ header files ・ libraries, packages ▸ create pyconfig.h, Makefile.pre ▸ makesetup Modules/Setup* ▸ create Makefile AC_CHECK_HEADERS([sys/random.h]) AC_CHECK_FUNCS([pthread_sigmask]) AC_CHECK_LIB([rt], [clock_nanosleep], [ AC_DEFINE([HAVE_CLOCK_NANOSLEEP], [1]) ]) AS_CASE([$ac_sys_system], [Emscripten], [EXEEXT=.js], [WASI], [EXEEXT=.wasm], ) // pyconfig.h #define HAVE_SYS_RANDOM_H 1 #define HAVE_PTHREAD_SIGMASK 1 #define HAVE_CLOCK_NANOSLEEP 1
  23. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Makefile 26 GNU make ▸ compile minimal core ▸ build "Programs/_freeze_module" ・ freeze "importlib_bootstrap.h" ▸ build "_bootstrap_python" ・ deep freeze stdlib core ▸ compile built-in modules ▸ build "python" executable ▸ compile shared extensions (distutils) ./python setup.py build BUILDPYTHON=python$(EXE) LINKCC=gcc -shared .PHONY: build_all build_all: $(BUILDPYTHON) $(BUILDPYTHON): Programs/python.o \ $(LINK_PYTHON_DEPS) $(LINKCC) $(PY_CORE_LDFLAGS) \ $(LINKFORSHARED) \ -o $@ Programs/python.o \ $(LINK_PYTHON_OBJS) \ $(LIBS) $(MODLIBS) $(SYSLIBS)
  24. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Cross-compile with Emscripten 27 EMSDK ▸ build system: x86_64-pc-linux-gnu ▸ target host: wasm32-unknown-emscripten ▸ cross compiler: emcc (Python script, Clang, LLVM, Binaryen, NodeJS) ▸ sysroot (headers, libraries) ▸ configure wrapper: emconfigure ▸ make wrapper: emmake Problem: _freeze_module, ./python setup.py
  25. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Cross compiling improvements 28 ▸ new wasm32 targets ▸ new --with-build-python ▸ re-implement _freeze_module in pure Python ▸ detect module deps in configure ▸ Modules/Setup.stdlib ▸ improved config.cache ▸ VPATH / out-of-tree build fixes ▸ new --with-emscripten-target # Makefile MODULE_ZLIB=yes MODULE_ZLIB_CFLAGS= MODULE_ZLIB_LDFLAGS=-lz MODULE__SCPROXY=n/a # Setup.stdlib.in @MODULE__SCPROXY_TRUE@_scproxy _scproxy.c @MODULE_ZLIB_TRUE@zlib zlibmodule.c # Setup.stdlib #_scproxy _scproxy.c zlib zlibmodule.c
  26. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    29 Build Python for browsers $ git clone https://github.com/python/cpython.git $ cd cpython $ mkdir -p builddir/build $ mkdir -p builddir/emscripten-browser $ cd builddir/emscripten-browser $ CONFIG_SITE=config.site-wasm32-emscripten \ emconfigure ../../configure \ --host=wasm32-unknown-emscripten \ --build=x86_64-pc-linux-gnu \ --with-emscripten-target=browser \ --with-build-python=$(pwd)/../build/python $ emmake make $ cd builddir/build $ ../../configure $ make $ ls python python $ cd ../.. $ ls python* python.data python.html python.js python.wasm python.worker.js # config site ac_cv_func_eventfd=no ac_cv_func_memfd_create=no
  27. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    30 Build container $ git clone .../cpython.git $ cd cpython $ podman run --rm -ti \ -v $(pwd):/python-wasm/cpython:Z \ quay.io/tiran/cpythonbuild:emsdk3 $ ./build-python-build.sh $ ./build-python-emscripten-browser.sh $ ./build-python-emscripten-node.sh $ ./Tools/wasm/wasm_webserver.py github.com/ethanhs/python-wasm/actions
  28. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    repl.ethanhs.me cheimes.fedorapeople.org/python-wasm 31
  29. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    > 60 CPython pull requests 32 https://bugs.python.org/issue40280 $ ./run-python-node.sh -c 'import _zoneinfo' builddir/emscripten-node/python.js:147 throw ex; ^ Error [RuntimeError]: function signature mismatch at module_dealloc (wasm-function[1908]) at _Py_Dealloc (wasm-function[1986]) at insertdict (wasm-function[1652]) at _PyDict_SetItem_Take2 (wasm-function[1641]) at dict_ass_sub (wasm-function[1733]) at PyObject_SetItem (wasm-function[495]) at finalize_modules (wasm-function[3677]) at Py_FinalizeEx (wasm-function[3674]) at Py_RunMain (wasm-function[4057]) at pymain_main (wasm-function[4060]) Emitted 'error' event on process instance at: at emitUnhandledRejectionOrErr at MessagePort.[nodejs.internal.kHybridDispatch] at MessagePort.exports.emitMessage --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -2612,7 +2612,7 @@ static PyTypeObject PyZoneInfo_ZoneInfoType = { // Specify the _zoneinfo module static PyMethodDef module_methods[] = {{NULL, NULL}}; static void -module_free(void) +module_free(void *m) {
  30. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Emscripten bug fixes 33 https://github.com/ethanhs/python-wasm/issues/43 ▸ Segfault in freeaddrinfo, memory leak in getaddrinfo ▸ clock_nanosleep() sleeps forever ▸ strftime() mishandles quoted percent, e.g. %%z ▸ week number of strftime("%U") and %W ▸ Fix edge case in strftime %V (ISO 8601 week number) ▸ opendir() leak file descriptor on error ▸ msync() on anon mapping fails with JS TypeError ▸ utimensat() sets wrong atime and mtime ▸ Blocking socket accept() fails with JS TypeError
  31. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    34 Browser ❌ subprocess (fork, exec) ❌ threads ❌ file system (only MEMFS) 🚧 shared extension modules ❌ PyPI packages ❓ sockets ❌ urllib, asyncio ❌ signals Node ❌ subprocess (fork, exec) ✅ threads ✅ file system (Node raw FS) 🚧 shared extension modules ❌ PyPI packages ❓ sockets ❌ urllib, asyncio 🚧 signals Supported features CPython 3.11 alpha 7 Pyodide ❌ subprocess (fork, exec) 🚧 threads ✅ file system (IDB, Node, …) ✅ shared extension modules ✅ PyPI packages ✅ WebAPI fetch / WebSocket ✅ signals
  32. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Frequently asked questions 35 ▸ Can I replace JavaScript with Python? No ▸ How large is the WASM binary? ~ 4.5 MB compressed with static, reduced stdlib 4.6 MB wasm (compressed 1.5 MB), 2.7 MB stdlib bytecode, some JS ▸ How fast is CPython in WebAssembly? 1.5 to 3 times slower than native (without optimizations) ▸ Will Python core officially support WASM? Not yet, maybe in the future ▸ What about Pyodide?
  33. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    38 Executable docs and examples Trey Hunner: www.pythonmorsels.com/paste/
  34. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    JupyterLite Jupyter ❤ WebAssembly ❤ Python jupyterlite.github.io/demo/lab/ 40
  35. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    41 Electron Visual Studio Code vscode.dev github.dev
  36. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    43 ▸ cocos2d ▸ freetype ▸ libGL ▸ libGL-emu ▸ libGL-webgl2 ▸ libjpeg ▸ libpng ▸ libwasmfs ▸ libwebgpu_cpp ▸ mpg123 ▸ ogg ▸ SDL2 ▸ SDL2_gfx ▸ SDL2_image ▸ SDL2_mixer ▸ SDL2_ttf ▸ vorbis ▸ zlib Emscripten ports Emscripten ported libraries ❓
  37. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Paul m. p. P. https://pmp-p.github.io/pygame-wasm/ 44
  38. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    WASI 45 WebAssembly System Interface ▸ no browser or JavaScript ▸ small runtimes (wasmtime 18 MB Rust binary) ▸ sandboxed ▸ capability-based security properties ▸ JIT or AOT (ahead-of-time) compilation to native code ▸ Wizer (WebAssembly Pre-Initializer) Wasmer wasmtime
  39. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    high-performance, secure, sandboxed Python edge computing 46
  40. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    47 ▸ numpy-1.22.3-cp310-cp310-win_amd64.whl ▸ numpy-1.22.3-cp310-cp310-win32.whl ▸ numpy-1.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl ▸ numpy-1.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl ▸ numpy-1.22.3-cp310-cp310-macosx_11_0_arm64.whl ▸ numpy-1.22.3-cp310-cp310-macosx_10_14_x86_64.whl ▸ numpy-1.22.3-cp39-cp39-win_amd64.whl ▸ numpy-1.22.3-cp39-cp39-win32.whl ▸ numpy-1.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl ▸ numpy-1.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl ▸ numpy-1.22.3-cp39-cp39-macosx_11_0_arm64.whl ▸ numpy-1.22.3-cp39-cp39-macosx_10_14_x86_64.whl ▸ numpy-1.22.3-cp38-cp38-win_amd64.whl ▸ numpy-1.22.3-cp38-cp38-win32.whl ▸ numpy-1.22.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl ▸ numpy-1.22.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl ▸ numpy-1.22.3-cp38-cp38-macosx_11_0_arm64.whl ▸ numpy-1.22.3-cp38-cp38-macosx_10_14_x86_64.whl numpy-1.22.3-cp311-abi3-wasm32.whl ▸ Python >= 3.11, <4 ▸ Any OS ▸ Any CPU architecture Python binary extension hell 3 Python versions, 3 CPU archs, 3 OSes: 18 wheels
  41. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    48 wasmtime for Python github.com/bytecodealliance/wasmtime-py from functools import partial from wasmtime import Store, Module, Instance store = Store() module = Module(store.engine, """ (module (export "line" (func $line)) (func $line (param $a f64) (param $x f64) (param $b f64) (result f64) get_local $a get_local $x f64.mul get_local $b f64.add ) )""") instance = Instance(store, module, []) line = instance.exports(store)["line"] line = partial(line, store) print(line(3., 5., 2.)) # 17.0
  42. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    Python on WebAssembly … a lot of opportunities! … a lot of work left to do! 49 ❤
  43. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    50 ▸ https://bugs.python.org/issue40280 ▸ https://github.com/ethanhs/python-wasm ▸ https://pyodide.org/ ▸ https://pmp-p.github.io/pygame-wasm ▸ https://jupyterlite.github.io/demo/lab/ ▸ https://assets.metacade.com/emulators/wi n311vr.html ▸ https://pypi.org/project/wasmtime/ ▸ https://mbebenita.github.io/WasmExplorer/ ▸ https://wasdk.github.io/WasmFiddle/ ▸ David Beazley Keynote PyCon India 2019 https://youtu.be/VUT386_GKI8 ▸ Lin Clark: A Cartoon Intro to WebAssembly https://youtu.be/HktWin_LPf4 Links & Resources https://repl.ethanhs.me https://cheimes.fedorapeople.org/python-wasm https://speakerdeck.com/tiran/
  44. PyConDE 2022: Python in the Browser, @ChristianHeimes, CC BY-SA 4.0

    linkedin.com/company/red-hat youtube.com/user/RedHatVideos facebook.com/redhatinc twitter.com/RedHat 51 Red Hat is the world’s leading provider of enterprise open source software solutions. Award-winning support, training, and consulting services make Red Hat a trusted adviser to the Fortune 500. Thank you