Python.exe: run code right here on the blog
See a Python snippet on this blog, press ▶ Try me, and it opens in
Python.exe, a little Notepad-style editor with an MS-DOS output pane.
Edit the code, press Run (or F5, like the good old days), and it
executes in your browser. No installs, no server, nothing sent anywhere.
Under the hood it's Pyodide, real CPython compiled to WebAssembly. The runtime (~10 MB) is downloaded only when you open the editor, and cached after that. If you never click, this page is as light as any other.
Start small
The classic, but make it 1998:
for greeting in ["Hello, World!", "It is now safe to run some Python."]:
print(greeting)
Change the strings, press F5, live a little.
Estimate π by throwing darts
Monte Carlo estimation: throw random darts at a square, count how many
land inside the circle. Crank n up and watch the estimate improve:
import random
def estimate_pi(n):
inside = sum(
1
for _ in range(n)
if random.random() ** 2 + random.random() ** 2 <= 1
)
return 4 * inside / n
for n in [100, 10_000, 1_000_000]:
print(f"n = {n:>9,} -> pi ~ {estimate_pi(n):.5f}")Check the math post's homework
In Math on this blog I claimed that . Don't take my word for it:
import math
partial = sum(1 / n**2 for n in range(1, 100_001))
print(f"sum of 1/n^2 (100k terms): {partial:.10f}")
print(f"pi^2 / 6: {math.pi**2 / 6:.10f}")Even numpy works
Imports of scientific packages are fetched automatically on first use.
numpy is an extra download (a few MB), so the first run takes a
moment. Here's the rotation matrix from the math post, as code:
import numpy as np
theta = np.radians(90)
R = np.array([
[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)],
])
x = np.array([1.0, 0.0])
print("x rotated 90 degrees:", np.round(R @ x, 3))Some snippets come pre-run
A block with a black Output pane under it didn't wait for you: it ran when this page was built, on a real CPython, and whatever it printed was pasted in. Read the answer without clicking, then click anyway if you don't believe it. Same code, two runtimes, and the pane is my problem if they ever disagree.
How much of a problem 1998 would have had with this page, for instance:
runtime_bytes = 10 * 1024 * 1024 # Pyodide, roughly
floppy_bytes = 1_474_560 # one 1.44 MB HD floppy, actual capacity
modem_kbps = 56 # V.90, downstream, on a good day
floppies = -(-runtime_bytes // floppy_bytes) # ceiling division
minutes = runtime_bytes * 8 / (modem_kbps * 1000) / 60
print(f"Python runtime: {runtime_bytes:,} bytes")
print(f"Floppy disks: {floppies} (label them 1 of {floppies}...)")
print(f"Over a 56k modem: {minutes:.0f} minutes")Python runtime: 10,485,760 bytes
Floppy disks: 8 (label them 1 of 8...)
Over a 56k modem: 25 minutesThe catch, for me rather than for you: a pre-run snippet has to print the same thing every time, or the post would quietly rewrite itself on every build. Which is exactly why the darts above aren't pre-run. Being different every time is the whole point of them.
The fine print
- Everything runs client-side in a sandbox, so you can't break the blog. Go wild.
- The editor shares one Python session per page visit, so variables survive between runs until you close the tab.
- File → Save writes to the virtual C:\ drive (your browser's localStorage). No cloud, no sync, no backups, just like a real hard drive from 1998.
- It runs on the page's main thread:
while True: passwill freeze the tab, exactly like it froze the family computer in 1998. Some traditions are worth keeping.