The online editor runs real CPython, compiled to WebAssembly, in four versions. Python 3.13 is the default. Choose another from the status line above the output.
| Where | Python |
|---|---|
| The editor (playground) | Any of the four. 3.13 until you choose another, and your choice is remembered. |
| The lessons, Tutorial Lab, programs, short answers, tips and error pages | 3.13 |
| The notebook | 3.13 |
| Code boxes embedded on other sites | 3.13 |
Everything outside the editor stays on 3.13 because every output printed on those pages was checked by running it on 3.13. On another version some of them would print something else, as the examples below show.
The editor remembers your choice for your next visit. A share link made on 3.14, 3.12 or 3.11 opens on that version for whoever you send it to, without changing their own choice.
Each example below was run in the editor on all four versions. The table shows what it printed, and the links open it on the version you pick.
Before 3.12, the quotes inside the braces of an f-string could not be the same kind as the quotes around it. Code written on a newer Python often does this, and it is a syntax error on 3.11.
scores = {"ana": 91, "ben": 78}
print(f"Ana scored {scores["ana"]}")| Python | What it prints |
|---|---|
| 3.11 | SyntaxError: f-string: unmatched '[' |
| 3.12, 3.13, 3.14 | Ana scored 91 |
Open it in the editor on Python 3.11 3.12 3.13 3.14
A short way to name a type, so a long type hint is written once.
type Point = tuple[float, float] def distance(a: Point, b: Point) -> float: return ((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) ** 0.5 print(distance((0, 0), (3, 4)))
| Python | What it prints |
|---|---|
| 3.11 | SyntaxError: invalid syntax |
| 3.12, 3.13, 3.14 | 5.0 |
Open it in the editor on Python 3.11 3.12 3.13 3.14
Each new version guesses what you meant in more places. 3.13 added a guess for a misspelled keyword argument, so the same mistake takes less hunting.
numbers = [3, 1, 2] print(sorted(numbers, reversed=True))
| Python | What it prints |
|---|---|
| 3.11, 3.12 | TypeError: 'reversed' is an invalid keyword argument for sort() |
| 3.13, 3.14 | TypeError: sort() got an unexpected keyword argument 'reversed'. Did you mean 'reverse'? |
Open it in the editor on Python 3.11 3.12 3.13 3.14
Make a changed copy of a dataclass (or a date, or a named tuple) in one call.
import copy from dataclasses import dataclass @dataclass class Point: x: int y: int p = Point(1, 2) print(copy.replace(p, x=10))
| Python | What it prints |
|---|---|
| 3.11, 3.12 | AttributeError: module 'copy' has no attribute 'replace' |
| 3.13, 3.14 | Point(x=10, y=2) |
Open it in the editor on Python 3.11 3.12 3.13 3.14
They look like f-strings, but give you the text and the values separately instead of joining them, so a library can check or escape the values first.
name = "Ana" greeting = t"Hello {name}!" print(type(greeting).__name__) print(greeting.strings, greeting.values)
| Python | What it prints |
|---|---|
| 3.11, 3.12, 3.13 | SyntaxError: invalid syntax |
| 3.14 | Template
('Hello ', '!') ('Ana',) |
Open it in the editor on Python 3.11 3.12 3.13 3.14
Catching two exception types no longer needs brackets around them.
try: int("abc") except ValueError, TypeError: print("not a number")
| Python | What it prints |
|---|---|
| 3.11, 3.12, 3.13 | SyntaxError: multiple exception types must be parenthesized |
| 3.14 | not a number |
Open it in the editor on Python 3.11 3.12 3.13 3.14
Python 3.11 here runs on an older Pyodide that cannot pause a program while it waits, so asyncio.run() does not work on 3.11 in this editor. It works on 3.12 and newer. On every version, you can write await at the top level instead.
import asyncio async def main(): await asyncio.sleep(0.1) return "done" print(asyncio.run(main()))
| Python | What it prints |
|---|---|
| 3.11 | RuntimeError: asyncio.run() does not work on Python 3.11 in this editor. (...) |
| 3.12, 3.13, 3.14 | done |
Open it in the editor on Python 3.11 3.12 3.13 3.14
The pandas version changes with the Python version here. Averaging a group that has a text column drops that column with a warning on 3.11 (pandas 1.5), and raises an error on the newer ones, with new wording on 3.14 (pandas 3.0).
import pandas as pd df = pd.DataFrame({"team": ["a", "a", "b"], "name": ["x", "y", "z"], "score": [1, 2, 3]}) print(df.groupby("team").mean())
| Python | What it prints |
|---|---|
| 3.11 | FutureWarning: The default value of numeric_only in DataFrameGroupBy.mean is deprecated. (...)
score
team
a 1.5
b 3.0 |
| 3.12, 3.13 | TypeError: agg function failed [how->mean,dtype->object] |
| 3.14 | TypeError: dtype 'str' does not support operation 'mean' |
Open it in the editor on Python 3.11 3.12 3.13 3.14
Each version comes with its own copy of the scientific packages, built for the browser:
| Package | 3.14 | 3.13 (default) | 3.12 | 3.11 |
|---|---|---|---|---|
| Exact version | 3.14.2 | 3.13.2 | 3.12.7 | 3.11.3 |
| NumPy | 2.4.6 | 2.2.5 | 2.0.2 | 1.26.4 |
| pandas | 3.0.2 | 2.3.0 | 2.2.3 | 1.5.3 |
| scikit-learn | 1.8.0 | 1.7.0 | 1.6.1 | 1.3.1 |
| Matplotlib | 3.10.8 | 3.8.4 | 3.8.4 | 3.5.2 |
| SciPy | 1.18.0 | 1.14.1 | 1.14.1 | 1.11.2 |
| pydantic | 2.12.5 | 2.10.6 | 2.10.5 | 1.10.7 |
| Compiled packages built in | 357 | 340 | 351 | 260 |
str type, and some errors are worded differently.The same on every version, because the code runs inside a browser tab:
| On a computer | In the browser |
|---|---|
subprocess, multiprocessing, threads | Not available. A browser tab cannot start programs or threads. |
tkinter, turtle | Not available: there are no desktop windows. |
| Any package from PyPI | Pure-Python packages, plus the compiled ones built for the browser. No PyTorch or TensorFlow. |
requests.get() to any website | Only to sites that allow requests from browsers (CORS), such as many public APIs. The editor explains the error when a site does not. |
urllib with https:// | Not available. Use requests. |
| Files on your disk | Files live in the browser’s storage. Upload them to the editor, and download what your code writes. |
| As much memory as the computer has | A few gigabytes at most. Very large data can stop the tab. |
Packages installed from PyPI are not tested in the browser by anyone, so now and then one installs but fails when it reaches something from the table above.
Python runs in the browser thanks to Pyodide, which builds CPython and its scientific packages for WebAssembly. Each Pyodide release carries one Python version, and the editor offers the newest release for each of 3.11, 3.12, 3.13 and 3.14. Python 3.10 is not offered: its browser build is from January 2023 and many current packages no longer install on it. Python 3.15 will be added when Pyodide’s first full release for it is out.
Python 3.13 by default, everywhere on the site. In the online editor you can switch to Python 3.14, 3.12 or 3.11 from the status line above the output. The lessons, examples, Tutorial Lab, notebook and embedded code boxes always run Python 3.13, the version their outputs were checked on.
Yes. Open the editor, click the status line that says Python 3.13.2 Ready and choose Python 3.14. It is real CPython 3.14 compiled to WebAssembly, so new syntax such as t-strings works. Nothing is installed and there is no account.
In the browser, packages with compiled parts have to be built for each release of Pyodide, the project that runs Python in the browser. Its last release for Python 3.11 came out in early 2024, so it carries NumPy 1.26 and pandas 1.5. A desktop install of Python 3.11 today would get newer versions, so some results can differ.
Packages written in pure Python install from PyPI on every version. Packages with compiled parts install only if Pyodide has built them for that version. PyTorch and TensorFlow have no browser build at all. If a package is missing on one version but available on another, the editor says which one.