2021-04-19 01:03:44 +00:00
|
|
|
|
# Frequently Asked Questions
|
2020-07-14 09:29:58 +00:00
|
|
|
|
|
2022-01-04 15:46:00 +00:00
|
|
|
|
(load-external-files-in-pyodide)=
|
2022-01-10 21:47:59 +00:00
|
|
|
|
|
2021-09-16 15:30:23 +00:00
|
|
|
|
## How can I load external files in Pyodide?
|
2020-07-14 09:29:58 +00:00
|
|
|
|
|
2022-06-22 03:15:37 +00:00
|
|
|
|
If you are using Pyodide in the browser, you should download external files and
|
|
|
|
|
save them to the virtual file system. The recommended way to do this is to zip
|
|
|
|
|
the files and unpack them into the file system with
|
|
|
|
|
{any}`pyodide.unpackArchive`:
|
2022-01-04 15:46:00 +00:00
|
|
|
|
|
2022-06-22 03:15:37 +00:00
|
|
|
|
```pyodide
|
|
|
|
|
let zipResponse = await fetch("myfiles.zip");
|
|
|
|
|
let zipBinary = await zipResponse.arrayBuffer();
|
|
|
|
|
pyodide.unpackArchive(zipBinary, "zip");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
You can also download the files from Python using {any}`pyodide.http.pyfetch`,
|
2022-01-04 15:46:00 +00:00
|
|
|
|
which is a convenient wrapper of JavaScript `fetch`:
|
|
|
|
|
|
|
|
|
|
```pyodide
|
2022-04-08 20:58:58 +00:00
|
|
|
|
await pyodide.runPythonAsync(`
|
2022-01-04 15:46:00 +00:00
|
|
|
|
from pyodide.http import pyfetch
|
2022-06-22 03:15:37 +00:00
|
|
|
|
response = await pyfetch("https://some_url/myfiles.zip")
|
|
|
|
|
await response.unpack_archive()
|
2022-01-04 15:46:00 +00:00
|
|
|
|
`)
|
|
|
|
|
```
|
|
|
|
|
|
2022-06-22 03:15:37 +00:00
|
|
|
|
If you are working in Node.js, you can mount a native folder into the file
|
|
|
|
|
system as follows:
|
|
|
|
|
|
2022-07-25 04:30:56 +00:00
|
|
|
|
```pyodide
|
2022-06-22 03:15:37 +00:00
|
|
|
|
FS.mkdir("/local_directory");
|
|
|
|
|
FS.mount(NODEFS, { root: "some/local/filepath" }, "/local_directory");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Then you can access the mounted folder from Python via the `/local_directory`
|
|
|
|
|
mount.
|
|
|
|
|
|
2022-01-04 15:46:00 +00:00
|
|
|
|
```{admonition} Why can't I just use urllib or requests?
|
|
|
|
|
:class: warning
|
|
|
|
|
|
|
|
|
|
We currently can’t use such packages since sockets are not available in Pyodide.
|
|
|
|
|
See {ref}`http-client-limit` for more information.
|
|
|
|
|
```
|
2020-07-14 09:29:58 +00:00
|
|
|
|
|
2020-10-30 20:09:25 +00:00
|
|
|
|
## Why can't I load files from the local file system?
|
2020-07-14 09:29:58 +00:00
|
|
|
|
|
2022-01-04 15:46:00 +00:00
|
|
|
|
For security reasons JavaScript in the browser is not allowed to load local data files
|
|
|
|
|
(for example, `file:///path/to/local/file.data`).
|
|
|
|
|
You will run into Network Errors, due to the [Same Origin Policy](https://en.wikipedia.org/wiki/Same-origin_policy).
|
|
|
|
|
There is a
|
2021-08-03 19:34:14 +00:00
|
|
|
|
[File System API](https://wicg.github.io/file-system-access/) supported in Chrome
|
|
|
|
|
but not in Firefox or Safari.
|
2020-12-24 17:14:49 +00:00
|
|
|
|
|
2022-01-04 15:46:00 +00:00
|
|
|
|
For development purposes, you can serve your files with a
|
|
|
|
|
[web server](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server).
|
|
|
|
|
|
2021-01-17 04:33:50 +00:00
|
|
|
|
## How can I execute code in a custom namespace?
|
2020-12-24 17:14:49 +00:00
|
|
|
|
|
2022-03-27 20:23:23 +00:00
|
|
|
|
The second argument to {any}`pyodide.runPython` is an options object which may
|
|
|
|
|
include a `globals` element which is a namespace for code to read from and write
|
|
|
|
|
to. The provided namespace must be a Python dictionary.
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2022-03-27 20:23:23 +00:00
|
|
|
|
```pyodide
|
|
|
|
|
let my_namespace = pyodide.globals.get("dict")();
|
|
|
|
|
pyodide.runPython(`x = 1 + 1`, { globals: my_namespace });
|
|
|
|
|
pyodide.runPython(`y = x ** x`, { globals: my_namespace });
|
|
|
|
|
my_namespace.get("y"); // ==> 4
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
You can also use this approach to inject variables from JavaScript into the
|
|
|
|
|
Python namespace, for example:
|
|
|
|
|
|
|
|
|
|
```pyodide
|
|
|
|
|
let my_namespace = pyodide.toPy({ x: 2, y: [1, 2, 3] });
|
|
|
|
|
pyodide.runPython(
|
|
|
|
|
`
|
|
|
|
|
assert x == y[1]
|
|
|
|
|
z = x ** x
|
|
|
|
|
`,
|
|
|
|
|
{ globals: my_namespace }
|
|
|
|
|
);
|
|
|
|
|
my_namespace.get("z"); // ==> 4
|
2021-02-15 19:38:07 +00:00
|
|
|
|
```
|
2020-11-07 11:21:54 +00:00
|
|
|
|
|
|
|
|
|
## How to detect that code is run with Pyodide?
|
|
|
|
|
|
2022-05-13 06:39:50 +00:00
|
|
|
|
**At run time**, you can check if Python is built with Emscripten (which is the
|
|
|
|
|
case for Pyodide) with,
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2020-11-07 11:21:54 +00:00
|
|
|
|
```py
|
|
|
|
|
import sys
|
|
|
|
|
|
2022-05-13 06:39:50 +00:00
|
|
|
|
if sys.platform == 'emscripten':
|
|
|
|
|
# running in Pyodide or other Emscripten based build
|
2020-11-07 11:21:54 +00:00
|
|
|
|
```
|
|
|
|
|
|
2022-05-13 06:39:50 +00:00
|
|
|
|
To detect that a code is running with Pyodide specifically, you can check
|
|
|
|
|
for the loaded `pyodide` module,
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2020-11-07 11:21:54 +00:00
|
|
|
|
```py
|
2022-05-13 06:39:50 +00:00
|
|
|
|
import sys
|
2020-11-07 11:21:54 +00:00
|
|
|
|
|
2022-05-13 06:39:50 +00:00
|
|
|
|
if "pyodide" in sys.modules:
|
|
|
|
|
# running in Pyodide
|
2020-11-07 11:21:54 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This however will not work at build time (i.e. in a `setup.py`) due to the way
|
2021-03-03 08:11:50 +00:00
|
|
|
|
the Pyodide build system works. It first compiles packages with the host compiler
|
2020-11-07 11:21:54 +00:00
|
|
|
|
(e.g. gcc) and then re-runs the compilation commands with emsdk. So the `setup.py` is
|
2021-04-12 16:34:02 +00:00
|
|
|
|
never run inside the Pyodide environment.
|
2020-11-07 11:21:54 +00:00
|
|
|
|
|
2021-03-03 08:11:50 +00:00
|
|
|
|
To detect Pyodide, **at build time** use,
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2020-11-07 11:21:54 +00:00
|
|
|
|
```python
|
|
|
|
|
import os
|
|
|
|
|
|
2021-01-01 07:48:28 +00:00
|
|
|
|
if "PYODIDE" in os.environ:
|
2020-11-07 11:21:54 +00:00
|
|
|
|
# building for Pyodide
|
|
|
|
|
```
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-01-01 07:48:28 +00:00
|
|
|
|
We used to use the environment variable `PYODIDE_BASE_URL` for this purpose,
|
|
|
|
|
but this usage is deprecated.
|
2021-01-17 04:33:50 +00:00
|
|
|
|
|
2021-09-29 08:01:53 +00:00
|
|
|
|
## How do I create custom Python packages from JavaScript?
|
2021-01-17 04:33:50 +00:00
|
|
|
|
|
2021-09-29 08:01:53 +00:00
|
|
|
|
Put a collection of functions into a JavaScript object and use {any}`pyodide.registerJsModule`:
|
|
|
|
|
JavaScript:
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-01-17 04:33:50 +00:00
|
|
|
|
```javascript
|
|
|
|
|
let my_module = {
|
2021-07-26 23:00:27 +00:00
|
|
|
|
f: function (x) {
|
|
|
|
|
return x * x + 1;
|
2021-01-17 04:33:50 +00:00
|
|
|
|
},
|
2021-07-26 23:00:27 +00:00
|
|
|
|
g: function (x) {
|
2021-01-17 04:33:50 +00:00
|
|
|
|
console.log(`Calling g on argument ${x}`);
|
|
|
|
|
return x;
|
|
|
|
|
},
|
2021-07-26 23:00:27 +00:00
|
|
|
|
submodule: {
|
|
|
|
|
h: function (x) {
|
|
|
|
|
return x * x - 1;
|
2021-01-17 04:33:50 +00:00
|
|
|
|
},
|
2021-07-26 23:00:27 +00:00
|
|
|
|
c: 2,
|
2021-03-20 18:56:10 +00:00
|
|
|
|
},
|
2021-01-17 04:33:50 +00:00
|
|
|
|
};
|
|
|
|
|
pyodide.registerJsModule("my_js_module", my_module);
|
|
|
|
|
```
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-01-17 04:33:50 +00:00
|
|
|
|
You can import your package like a normal Python package:
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-02-15 08:38:49 +00:00
|
|
|
|
```py
|
2021-01-17 04:33:50 +00:00
|
|
|
|
import my_js_module
|
|
|
|
|
from my_js_module.submodule import h, c
|
|
|
|
|
assert my_js_module.f(7) == 50
|
|
|
|
|
assert h(9) == 80
|
|
|
|
|
assert c == 2
|
2021-04-06 08:14:07 +00:00
|
|
|
|
```
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-12 16:34:02 +00:00
|
|
|
|
## How can I send a Python object from my server to Pyodide?
|
|
|
|
|
|
|
|
|
|
The best way to do this is with pickle. If the version of Python used in the
|
|
|
|
|
server exactly matches the version of Python used in the client, then objects
|
|
|
|
|
that can be successfully pickled can be sent to the client and unpickled in
|
|
|
|
|
Pyodide. If the versions of Python are different then for instance sending AST
|
|
|
|
|
is unlikely to work since there are breaking changes to Python AST in most
|
|
|
|
|
Python minor versions.
|
|
|
|
|
|
|
|
|
|
Similarly when pickling Python objects defined in a Python package, the package
|
|
|
|
|
version needs to match exactly between the server and pyodide.
|
|
|
|
|
|
|
|
|
|
Generally, pickles are portable between architectures (here amd64 and wasm32).
|
|
|
|
|
The rare cases when they are not portable, for instance currently tree based
|
|
|
|
|
models in scikit-learn, can be considered as a bug in the upstream library.
|
|
|
|
|
|
|
|
|
|
```{admonition} Security Issues with pickle
|
|
|
|
|
:class: warning
|
|
|
|
|
|
|
|
|
|
Unpickling data is similar to `eval`. On any public-facing server it is a really
|
|
|
|
|
bad idea to unpickle any data sent from the client. For sending data from client
|
|
|
|
|
to server, try some other serialization format like JSON.
|
|
|
|
|
```
|
2021-04-18 06:23:18 +00:00
|
|
|
|
|
2021-09-11 23:34:45 +00:00
|
|
|
|
## How can I use a Python function as an event handler?
|
2021-04-18 06:23:18 +00:00
|
|
|
|
|
|
|
|
|
Note that the most straight forward way of doing this will not work:
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-18 06:23:18 +00:00
|
|
|
|
```py
|
|
|
|
|
from js import document
|
|
|
|
|
def f(*args):
|
|
|
|
|
document.querySelector("h1").innerHTML += "(>.<)"
|
|
|
|
|
|
|
|
|
|
document.body.addEventListener('click', f)
|
|
|
|
|
```
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-09-16 15:30:23 +00:00
|
|
|
|
Now every time you click, an error will be raised (see {ref}`call-js-from-py`).
|
2021-04-18 06:23:18 +00:00
|
|
|
|
|
2021-09-11 23:34:45 +00:00
|
|
|
|
To do this correctly use {func}`pyodide.create_proxy` as follows:
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-18 06:23:18 +00:00
|
|
|
|
```py
|
|
|
|
|
from js import document
|
|
|
|
|
from pyodide import create_proxy
|
|
|
|
|
def f(*args):
|
|
|
|
|
document.querySelector("h1").innerHTML += "(>.<)"
|
|
|
|
|
|
|
|
|
|
proxy_f = create_proxy(f)
|
|
|
|
|
document.body.addEventListener('click', proxy_f)
|
|
|
|
|
# Store proxy_f in Python then later:
|
|
|
|
|
document.body.removeEventListener('click', proxy_f)
|
|
|
|
|
proxy_f.destroy()
|
|
|
|
|
```
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-18 14:10:45 +00:00
|
|
|
|
## How can I use fetch with optional arguments from Python?
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-09-29 08:01:53 +00:00
|
|
|
|
The most obvious translation of the JavaScript code won't work:
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-18 14:10:45 +00:00
|
|
|
|
```py
|
2021-04-19 15:09:29 +00:00
|
|
|
|
import json
|
2021-04-18 14:10:45 +00:00
|
|
|
|
resp = await js.fetch('/someurl', {
|
2021-04-20 15:32:15 +00:00
|
|
|
|
"method": "POST",
|
|
|
|
|
"body": json.dumps({ "some" : "json" }),
|
|
|
|
|
"credentials": "same-origin",
|
|
|
|
|
"headers": { "Content-Type": "application/json" }
|
2021-04-18 14:10:45 +00:00
|
|
|
|
})
|
|
|
|
|
```
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-09-11 23:34:45 +00:00
|
|
|
|
The `fetch` API ignores the options that we attempted to provide. You can do
|
2021-09-16 15:30:23 +00:00
|
|
|
|
this correctly in one of two ways:
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-18 14:10:45 +00:00
|
|
|
|
```py
|
2021-04-19 15:09:29 +00:00
|
|
|
|
import json
|
2022-06-28 13:31:58 +00:00
|
|
|
|
from pyodide.ffi import to_js
|
2021-04-20 15:32:15 +00:00
|
|
|
|
from js import Object
|
2021-04-18 14:10:45 +00:00
|
|
|
|
resp = await js.fetch('example.com/some_api',
|
|
|
|
|
method= "POST",
|
2021-04-19 15:09:29 +00:00
|
|
|
|
body= json.dumps({ "some" : "json" }),
|
2021-04-18 14:10:45 +00:00
|
|
|
|
credentials= "same-origin",
|
2021-04-20 15:32:15 +00:00
|
|
|
|
headers= Object.fromEntries(to_js({ "Content-Type": "application/json" })),
|
2021-04-18 14:10:45 +00:00
|
|
|
|
)
|
|
|
|
|
```
|
2021-04-22 08:34:07 +00:00
|
|
|
|
|
2021-09-16 15:30:23 +00:00
|
|
|
|
or:
|
|
|
|
|
|
|
|
|
|
```py
|
|
|
|
|
import json
|
2022-06-28 13:31:58 +00:00
|
|
|
|
from pyodide.ffi import to_js
|
2021-09-16 15:30:23 +00:00
|
|
|
|
from js import Object
|
|
|
|
|
resp = await js.fetch('example.com/some_api', to_js({
|
|
|
|
|
"method": "POST",
|
|
|
|
|
"body": json.dumps({ "some" : "json" }),
|
|
|
|
|
"credentials": "same-origin",
|
|
|
|
|
"headers": { "Content-Type": "application/json" }
|
|
|
|
|
}, dict_converter=Object.fromEntries)
|
|
|
|
|
```
|
|
|
|
|
|
2021-04-22 08:34:07 +00:00
|
|
|
|
## How can I control the behavior of stdin / stdout / stderr?
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-09-16 15:30:23 +00:00
|
|
|
|
If you wish to override `stdin`, `stdout` or `stderr` for the entire Pyodide
|
|
|
|
|
runtime, you can pass options to {any}`loadPyodide <globalThis.loadPyodide>`: If
|
|
|
|
|
you say
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
loadPyodide({
|
2022-03-21 05:44:54 +00:00
|
|
|
|
stdin: stdin_func, stdout: stdout_func, stderr: stderr_func
|
2021-09-16 15:30:23 +00:00
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
then every time a line is written to `stdout` (resp. `stderr`), `stdout_func`
|
2022-03-08 05:51:20 +00:00
|
|
|
|
(resp `stderr_func`) will be called on the line. Every time `stdin` is read,
|
2021-09-16 15:30:23 +00:00
|
|
|
|
`stdin_func` will be called with zero arguments. It is expected to return a
|
|
|
|
|
string which is interpreted as a line of text.
|
|
|
|
|
|
|
|
|
|
Temporary redirection works much the same as it does in native Python: you can
|
|
|
|
|
overwrite `sys.stdin`, `sys.stdout`, and `sys.stderr` respectively. If you want
|
|
|
|
|
to do it temporarily, it's recommended to use
|
2021-04-22 08:34:07 +00:00
|
|
|
|
[`contextlib.redirect_stdout`](https://docs.python.org/3/library/contextlib.html#contextlib.redirect_stdout)
|
|
|
|
|
and
|
2021-04-22 08:49:13 +00:00
|
|
|
|
[`contextlib.redirect_stderr`](https://docs.python.org/3/library/contextlib.html#contextlib.redirect_stderr).
|
2021-09-16 15:30:23 +00:00
|
|
|
|
There is no `contextlib.redirect_stdin` but it is easy to make your own as
|
|
|
|
|
follows:
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-22 08:34:07 +00:00
|
|
|
|
```py
|
|
|
|
|
from contextlib import _RedirectStream
|
|
|
|
|
class redirect_stdin(_RedirectStream):
|
|
|
|
|
_stream = "stdin"
|
|
|
|
|
```
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-22 08:34:07 +00:00
|
|
|
|
For example, if you do:
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-22 08:34:07 +00:00
|
|
|
|
```
|
|
|
|
|
from io import StringIO
|
|
|
|
|
with redirect_stdin(StringIO("\n".join(["eval", "asyncio.ensure_future", "functools.reduce", "quit"]))):
|
|
|
|
|
help()
|
|
|
|
|
```
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-22 08:34:07 +00:00
|
|
|
|
it will print:
|
2021-07-26 23:00:27 +00:00
|
|
|
|
|
2021-04-22 08:34:07 +00:00
|
|
|
|
```
|
2022-03-17 22:48:56 +00:00
|
|
|
|
Welcome to Python 3.10's help utility!
|
2021-04-22 08:34:07 +00:00
|
|
|
|
<...OMITTED LINES>
|
|
|
|
|
Help on built-in function eval in module builtins:
|
|
|
|
|
eval(source, globals=None, locals=None, /)
|
|
|
|
|
Evaluate the given source in the context of globals and locals.
|
|
|
|
|
<...OMITTED LINES>
|
|
|
|
|
Help on function ensure_future in asyncio:
|
|
|
|
|
asyncio.ensure_future = ensure_future(coro_or_future, *, loop=None)
|
|
|
|
|
Wrap a coroutine or an awaitable in a future.
|
|
|
|
|
<...OMITTED LINES>
|
|
|
|
|
Help on built-in function reduce in functools:
|
|
|
|
|
functools.reduce = reduce(...)
|
|
|
|
|
reduce(function, sequence[, initial]) -> value
|
|
|
|
|
Apply a function of two arguments cumulatively to the items of a sequence,
|
|
|
|
|
<...OMITTED LINES>
|
|
|
|
|
You are now leaving help and returning to the Python interpreter.
|
|
|
|
|
```
|
2022-05-17 18:07:36 +00:00
|
|
|
|
|
|
|
|
|
## Micropip can't find a pure Python wheel
|
|
|
|
|
|
|
|
|
|
When installing a Python package from PyPI, micropip will produce an error if
|
|
|
|
|
it cannot find a pure Python wheel. To determine if a package has a pure
|
|
|
|
|
Python wheel manually, you can open its PyPi page (for instance
|
|
|
|
|
https://pypi.org/project/snowballstemmer/) and go to the "Download files" tab.
|
|
|
|
|
If this tab doesn't contain a file `*py3-none-any.whl` then the pure Python
|
|
|
|
|
wheel is missing.
|
|
|
|
|
|
|
|
|
|
This can happen for two reasons,
|
|
|
|
|
|
|
|
|
|
1. either the package is pure Python (you can check language composition for a
|
|
|
|
|
package on Github), and its maintainers didn't upload a wheel.
|
|
|
|
|
In this case, you can report this issue to the package issue tracker. As a
|
|
|
|
|
temporary solution, you can also [build the
|
|
|
|
|
wheel](https://packaging.python.org/en/latest/tutorials/packaging-projects/#generating-distribution-archives)
|
|
|
|
|
yourself, upload it to some temporary location and install it with micropip
|
|
|
|
|
from the corresponding URL.
|
|
|
|
|
2. or the package has binary extensions (e.g. C, Fortran or Rust), in which
|
|
|
|
|
case it needs to be packaged in Pyodide. Please open [an
|
|
|
|
|
issue](https://github.com/pyodide/pyodide/issues) after checking than an
|
|
|
|
|
issue for this opackage doesn't exist already. Then follow
|
|
|
|
|
{ref}`new-packages`.
|
2022-06-22 03:15:37 +00:00
|
|
|
|
|
|
|
|
|
## How can I change the behavior of {any}`runPython <pyodide.runPython>` and {any}`runPythonAsync <pyodide.runPythonAsync>`?
|
|
|
|
|
|
|
|
|
|
You can directly call Python functions from JavaScript. For most purposes it
|
|
|
|
|
makes sense to make your own Python function as an entrypoint and call that
|
|
|
|
|
instead of redefining `runPython`. The definitions of {any}`runPython <pyodide.runPython>` and {any}`runPythonAsync <pyodide.runPythonAsync>` are very
|
|
|
|
|
simple:
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
function runPython(code) {
|
2022-06-26 04:20:22 +00:00
|
|
|
|
pyodide.pyodide_py.code.eval_code(code, pyodide.globals);
|
2022-06-22 03:15:37 +00:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
async function runPythonAsync(code) {
|
2022-06-26 04:20:22 +00:00
|
|
|
|
return await pyodide.pyodide_py.code.eval_code_async(code, pyodide.globals);
|
2022-06-22 03:15:37 +00:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
To make your own version of {any}`runPython <pyodide.runPython>` you could do:
|
|
|
|
|
|
|
|
|
|
```pyodide
|
|
|
|
|
const my_eval_code = pyodide.runPython(`
|
2022-06-26 04:20:22 +00:00
|
|
|
|
from pyodide.code import eval_code
|
2022-06-22 03:15:37 +00:00
|
|
|
|
def my_eval_code(code, ns):
|
|
|
|
|
extra_info = None
|
2022-06-26 04:20:22 +00:00
|
|
|
|
result = eval_code(code, ns)
|
2022-06-22 03:15:37 +00:00
|
|
|
|
return ns["extra_info"], result
|
|
|
|
|
my_eval_code
|
|
|
|
|
`)
|
|
|
|
|
|
|
|
|
|
function myRunPython(code){
|
|
|
|
|
return my_eval_code(code, pyodide.globals);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Then `myRunPython("2+7")` returns `[None, 9]` and
|
|
|
|
|
`myRunPython("extra_info='hello' ; 2 + 2")` returns `['hello', 4]`.
|
|
|
|
|
If you want to change which packages {any}`pyodide.loadPackagesFromImports` loads, you can
|
2022-06-26 04:20:22 +00:00
|
|
|
|
monkey patch {any}`pyodide.code.find_imports` which takes `code` as an argument
|
2022-06-22 03:15:37 +00:00
|
|
|
|
and returns a list of packages imported.
|