pyodide / pyodide/pyodide

Make top-level await support an opt-in

Open
#3,587 11 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
14.8k
Forks
1k
Avg merge
20h 29m
Merged PRs (30d)
19

Description

## Proposed refactoring

The top-level await support is always enabled in Pyodide. We propose to make the feature an opt-in, or at least document a way how to opt-out from this feature.

### Motivation

The benefits of the top-level await support in the [console.html](https://pyodide.org/en/stable/console.html) are clear, however, at the cost of deviation from the standard CPython interpreter behavior. Consider this example:

in pyoidide console.html:
```
Welcome to the Pyodide terminal emulator 🐍
Python 3.10.2 (main, Jan 25 2023 18:32:53) on WebAssembly/Emscripten
Type "help", "copyright", "credits" or "license" for more information.
>>> async def fun():
... print("test")
...
>>> await fun()
test
>>>
```

the same in standard python interpreter:
```
Python 3.10.8 (main, Nov 1 2022, 14:18:21) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> async def fun():
... print("test")
...
>>> await fun()
File "", line 1
SyntaxError: 'await' outside function
```

In pyodide, the top-level await works out of the box, while in CPython, this throws SyntaxError. However, the feature also has its darker side:

in standard python interpreter:
```
Python 3.10.8 (main, Nov 1 2022, 14:18:21) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import asyncio
>>> async def fun():
... print("test")
...
>>> asyncio.run(fun())
test
>>>
```

However, this code will fail in pyodide:
```
Welcome to the Pyodide terminal emulator 🐍
Python 3.10.2 (main, Jan 25 2023 18:32:53) on WebAssembly/Emscripten
Type "help", "copyright", "credits" or "license" for more information.
>>> import asyncio
>>> async def fun():
... print("test")
...
>>> asyncio.run(fun())
Traceback (most recent call last):
File "", line 1, in
File "/lib/python3.10/asyncio/runners.py", line 33, in run
raise RuntimeError(
RuntimeError: asyncio.run() cannot be called from a running event loop
>>>
```

It is not clear to us how to make this code work with Pyodide, and how to escape the top-level await hatch. The motivation is that more advanced users might want to change Pyodide's WebLoop for some other Event Loop, but we do not see a way how to close or disable the WebLoop.

### Pitch

We propose to move the WebLoop initialization code from the Pyodide's init to the application itself (console.html), as shown in our [PR draft](https://github.com/ozobot/pyodide/pull/2). This will not break the functionality users expect from console.html, but will harmonize the default behavior of Pyodide with CPython.

### Additional context

The top-level await feature was enabled by adding the WebLoop in PR #1158.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.