@@ -23,9 +23,9 @@ https://github.com/psf/webassembly for more information.
23
23
24
24
To cross compile to the `` wasm32-emscripten `` platform you need
25
25
[ the Emscripten compiler toolchain] ( https://emscripten.org/ ) ,
26
- a Python interpreter, and an installation of Node version 18 or newer. Emscripten
27
- version 3.1.42 or newer is recommended. All commands below are relative to a checkout
28
- of the Python repository.
26
+ a Python interpreter, and an installation of Node version 18 or newer.
27
+ Emscripten version 3.1.73 or newer is recommended. All commands below are
28
+ relative to a checkout of the Python repository.
29
29
30
30
#### Install [ the Emscripten compiler toolchain] ( https://emscripten.org/docs/getting_started/downloads.html )
31
31
@@ -50,7 +50,7 @@ sourced. Otherwise the source script removes the environment variable.
50
50
export EM_COMPILER_WRAPPER=ccache
51
51
```
52
52
53
- ### Compile and build Python interpreter
53
+ #### Compile and build Python interpreter
54
54
55
55
You can use ` python Tools/wasm/emscripten ` to compile and build targetting
56
56
Emscripten. You can do everything at once with:
@@ -70,6 +70,88 @@ instance, to do a debug build, you can use:
70
70
python Tools/wasm/emscripten build --with-py-debug
71
71
```
72
72
73
+ ### Running from node
74
+
75
+ If you want to run the normal Python CLI, you can use ` python.sh ` . It takes the
76
+ same options as the normal Python CLI entrypoint, though the REPL does not
77
+ function and will crash.
78
+
79
+ ` python.sh ` invokes ` node_entry.mjs ` which imports the Emscripten module for the
80
+ Python process and starts it up with the appropriate settings. If you wish to
81
+ make a node application that "embeds" the interpreter instead of acting like the
82
+ CLI you will need to write your own alternative to ` node_entry.mjs ` .
83
+
84
+
85
+ ### The Web Example
86
+
87
+ When building for Emscripten, the web example will be built automatically. It is
88
+ in the `` web_example `` directory. To run the web example, `` cd `` into the
89
+ `` web_example `` directory, then run `` python server.py `` . This will start a web
90
+ server; you can then visit `` http://localhost:8000/python.html `` in a browser to
91
+ see a simple REPL example.
92
+
93
+ The web example relies on a bug fix in Emscripten version 3.1.73 so if you build
94
+ with earlier versions of Emscripten it may not work. The web example uses
95
+ `` SharedArrayBuffer `` . For security reasons browsers only provide
96
+ `` SharedArrayBuffer `` in secure environments with cross-origin isolation. The
97
+ webserver must send cross-origin headers and correct MIME types for the
98
+ JavaScript and WebAssembly files. Otherwise the terminal will fail to load with
99
+ an error message like `` ReferenceError: SharedArrayBuffer is not defined `` . See
100
+ more information here:
101
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements
102
+
103
+ Note that `` SharedArrayBuffer `` is _ not required_ to use Python itself, only the
104
+ web example. If cross-origin isolation is not appropriate for your use case you
105
+ may make your own application embedding ` python.mjs ` which does not use
106
+ `` SharedArrayBuffer `` and serve it without the cross-origin isolation headers.
107
+
108
+ ### Embedding Python in a custom JavaScript application
109
+
110
+ You can look at ` python.worker.mjs ` and ` node_entry.mjs ` for inspiration. At a
111
+ minimum you must import `` createEmscriptenModule `` and you need to call
112
+ `` createEmscriptenModule `` with an appropriate settings object. This settings
113
+ object will need a prerun hook that installs the Python standard library into
114
+ the Emscripten file system.
115
+
116
+ #### NodeJs
117
+
118
+ In Node, you can use the NodeFS to mount the standard library in your native
119
+ file system into the Emscripten file system:
120
+ ``` js
121
+ import createEmscriptenModule from " ./python.mjs" ;
122
+
123
+ await createEmscriptenModule ({
124
+ preRun (Module ) {
125
+ Module .FS .mount (
126
+ Module .FS .filesystems .NODEFS ,
127
+ { root: " /path/to/python/stdlib" },
128
+ " /lib/" ,
129
+ );
130
+ },
131
+ });
132
+ ```
133
+
134
+ #### Browser
135
+
136
+ In the browser, the simplest approach is to put the standard library in a zip
137
+ file it and install it. With Python 3.14 this could look like:
138
+ ``` js
139
+ import createEmscriptenModule from " ./python.mjs" ;
140
+
141
+ await createEmscriptenModule ({
142
+ async preRun (Module ) {
143
+ Module .FS .mkdirTree (" /lib/python3.14/lib-dynload/" );
144
+ Module .addRunDependency (" install-stdlib" );
145
+ const resp = await fetch (" python3.14.zip" );
146
+ const stdlibBuffer = await resp .arrayBuffer ();
147
+ Module .FS .writeFile (` /lib/python314.zip` , new Uint8Array (stdlibBuffer), {
148
+ canOwn: true ,
149
+ });
150
+ Module .removeRunDependency (" install-stdlib" );
151
+ },
152
+ });
153
+ ```
154
+
73
155
### Limitations and issues
74
156
75
157
#### Network stack
@@ -151,38 +233,6 @@ python Tools/wasm/emscripten build --with-py-debug
151
233
- Test modules are disabled by default. Use `` --enable-test-modules `` build
152
234
test modules like `` _testcapi `` .
153
235
154
- ### wasm32-emscripten in node
155
-
156
- Node builds use `` NODERAWFS `` .
157
-
158
- - Node RawFS allows direct access to the host file system without need to
159
- perform `` FS.mount() `` call.
160
-
161
- ### Hosting Python WASM builds
162
-
163
- The simple REPL terminal uses SharedArrayBuffer. For security reasons
164
- browsers only provide the feature in secure environments with cross-origin
165
- isolation. The webserver must send cross-origin headers and correct MIME types
166
- for the JavaScript and WASM files. Otherwise the terminal will fail to load
167
- with an error message like `` Browsers disable shared array buffer `` .
168
-
169
- #### Apache HTTP .htaccess
170
-
171
- Place a `` .htaccess `` file in the same directory as `` python.wasm `` .
172
-
173
- ```
174
- # .htaccess
175
- Header set Cross-Origin-Opener-Policy same-origin
176
- Header set Cross-Origin-Embedder-Policy require-corp
177
-
178
- AddType application/javascript js
179
- AddType application/wasm wasm
180
-
181
- <IfModule mod_deflate.c>
182
- AddOutputFilterByType DEFLATE text/html application/javascript application/wasm
183
- </IfModule>
184
- ```
185
-
186
236
## WASI (wasm32-wasi)
187
237
188
238
See [ the devguide on how to build and run for WASI] ( https://devguide.python.org/getting-started/setup-building/#wasi ) .
0 commit comments