Two editors, one Python
Both playgrounds below import the same runtime module, so they share a single Web Worker and a single Pyodide instance. Run them back to back: the second one does not reboot anything. Run them at the same time and the second waits — Python is single-threaded, so runs are queued.
Running… but only starts once B finishes. If each
widget had its own Pyodide, both would boot ~11 MB separately.
Stopping runaway code
There is no cooperative interrupt without SharedArrayBuffer (which needs site-wide COOP/COEP headers), so Stop terminates the worker and boots a fresh one. Queued runs survive and land on the new worker.
Reading input
input() really blocks: the prompt appears, a caret waits in
the output, and the program continues when you answer. What you type is
echoed the way a terminal echoes it, so the transcript reads back
properly. Enter sends a line, EOF ends input.
The standard-input box is optional now — lines in it are used up first, before you are asked. Handy for scripted exercises; leave it empty to answer live.
Prompting in a loop works the same way — press EOF or send a blank line to stop.
Packages load themselves
loadPackagesFromImports() runs before your code, so an import is all it takes.
Light and dark
Press theme in the header. Widgets default to
theme="auto", which follows this page's switch — it sets
color-scheme on the root, and that is all the widget needs.
An explicit theme overrides it: the pair below stays put
whichever way you toggle.
Sizing
height="auto" fits the snippet — no dead space under a
one-liner, no hidden lines under a long one, at any viewport width.
max-height caps a long listing and scrolls inside it.
min-height gives a short exercise room to type in — the
whole box is the editor, not just the first line.