Skip to content

d/Python · the first Python for 8-bit home computers

Python 3, everywhere.
Even on an 8-bit machine.

d/Python is the first Python for 8-bit home computers. You write ordinary Python 3. It compiles to one small program file that runs the same way everywhere: in your browser right now, on your Mac today, on Linux and Windows next, and on the Atari 800, Commodore 64 and Apple II under d/OS, the operating system that brings modern software to those machines. Windows, buttons, games and sound are plain Python calls. Nothing else ships with your program: no interpreter, no CPython.

  • The real compiler, running in your browser
  • Nothing you type is uploaded
  • input() waits for your answer
  • Windows, buttons, sound and a game
fibonacci.py · 12 lines · compiles to 1,561 bytes · right here. Output: Fibonacci of 100 and two to the hundredth power, both exact.
# Python integers grow with the result; no fixed-width overflow.
def fibonacci(count):
    a = 0
    b = 1
    for i in range(count):
        previous = a
        a = b
        b = previous + b
    return a

print("Fibonacci(100):", fibonacci(100))
print("Two to the hundredth:", 2 ** 100)
Run it live

Why d/Python exists

Python is one of the most popular programming languages in the world, and one of the friendliest to learn. The home computers people still love, the Atari 800, the Commodore 64 and the Apple II, never got it: Python came along years later and needs more machine than they have. d/Python is the first Python for 8-bit home computers. It is a version of Python built so those machines can have it too. It belongs to d/OS, the operating system that brings modern software to those same 8-bit machines, and it keeps the d/OS way whole: one compiled program for every machine, windows and drawing as ordinary function calls, and no interpreter shipped with your program. It runs today in your browser and on your desktop. Every number on this page was measured on the very compiler you are about to use. Read the lineage ↓

62 / 62single-file test programs that run in this browser and print exactly, byte for byte, what the reference CPython build (3.9.6) prints
0bytes of CPython in your program or in the runtime; the compiler is written in Rust, your program becomes a small compiled file, .dbc, and the same file runs everywhere
191intents, named requests to the machine such as "fill this rectangle", that you can call from Python: graphics, on-screen widgets, files, sound, network, math and hashing; 86 have already been run and checked in tests
45rows in the compatibility table, each saying what has been tested and what still stands in the way; none is marked complete

Three doors, one language

The idea in one screen

class Counter:
    def __init__(self, start):
        self.value = start

    def __call__(self, amount=1, /, *, scale=1):
        self.value += amount * scale
        return self.value

counter = Counter(7)
print("Counter:", counter(), counter(2, scale=3))
print("Sorted by magnitude:", sorted([-3, 1, -1, 2], key=abs))
print("A big number:", 2 ** 100)

That is ordinary Python 3: a class you can call like a function, parameters that must be given by position or by name, a builtin used as a sort key, and an integer far too big for a machine word. The unusual part happens after the source leaves your editor, because the target is every machine at once:

.py source → RustPython parser → Python analysis → bytecode → optimizer → validation → .dbc program + the .dbl libraries it uses → browser · macOS · Windows · Linux · Atari · C64 · Apple II

There is one bytecode and one set of runtime rules. A host machine chooses how to provide graphics, sound, storage, network and windows; it does not get a private dialect of the language. That is the property the whole design exists for: write it once, and the same bytes mean the same thing on a web page, in a desktop window, and on a 6502 with a cartridge acting as its coprocessor. The bytecode, the runtime and the list of intents are shared with d/BASIC, d/OS's other language, so a Python program is a full d/OS application with the same windows, packages and developer seals. Python keeps its own rules throughout, and the conformance rules forbid trading them for anything.

What d/Python keeps

Python should stay Python

-7 // 2 is -4. 2 ** 100 is exact. Assign a list to a second name and both names point at the same list. Arguments bind by Python's rules, default values are worked out once, and inner functions share variables with the function around them. The d/OS runtime, the program that runs your compiled code, inherited its number types from QuickBASIC; d/Python's promises say that is a fact about the implementation, never permission to give Python BASIC's rules.

print(-7 // 2, -7 % 2, divmod(-7, 2))
print(2 ** 100 % 97, pow(7, 13, -19))

No interpreter should ship

A compiled d/Python program is bytecode plus the support libraries it actually uses, each one identified by its hash. Big integers live in a shared library file, .dbl; a program whose numbers never outgrow a machine word never links it. Nothing of CPython travels with your program, and no Python source is needed to run it.

# fibonacci.py links one library: dpython.integers
print("Two to the hundredth:", 2 ** 100)

One bytecode should reach every machine

The program you compile here is the program that runs on a Mac, and the program designed to run on an Atari 800, a Commodore 64 or an Apple II under d/OS. The runtime is shared with d/BASIC, and the same tests written in both languages run in the same runtime and compare every call, result and effect, so a host cannot quietly mean something different.

import dos
values = dos.array("f64", [1.25, 2.5])
total = dos.intent("MATH", "ARRAY_REDUCE", 0, 4, 2, values, values)
print(total == 3.75)

Gaps should be named, not silent

Ask for float(), open() or a string method that is not there yet and the compiler stops at the line and column and tells you, in words, exactly what is missing. It never compiles something slightly different and lets you find out later. The compatibility table lists every boundary and what stands behind it, and something supported in part is never called complete.

main.py:1:5: call to `float` is not supported yet

d/OS owns the window

Your handlers run in short, bounded turns that d/OS schedules; the screen never waits on a program. On-screen widgets belong to the shared UI engine, which does the drawing and keeps track of what changed, so an application asks for one UI.SYNC and never repaints by hand. The same rule applies to d/BASIC.

# fragment: the whole draw handler of a retained-widget program
@dos.on("WINDOW_DRAW")
def draw_window():
    dos.intent("UI", "SYNC", root.node)

Programs say what they want, hosts provide what they can

dos.intent("GFX", "FILL_RECT", …) is an intent: a named request that the machine carries out however it can. It means the same thing on a web page, in a Mac window and on an 8-bit machine with a cartridge coprocessor. The Python bindings for graphics, widgets, files, sound, network, math and hashing are generated from the official list of intents. A program declares what it needs, and a host that lacks it declines before the first instruction runs.

# fragment: one intent, the same on every host
dos.intent("GFX", "FILL_RECT", 0, 0, 320, 200, 4226)

From a Christmas project to the dock

  • 1989 · December, Amsterdam. Guido van Rossum starts writing Python over the Christmas holidays at CWI, as a successor to ABC that could also do systems work.1 Indentation is part of the syntax from the first day.
  • 1991 · February 20. Python 0.9.0 is posted to alt.sources: classes with inheritance, exceptions, functions, and the list, dict and str types.2
  • 1994 · January. Python 1.0, with lambda, map, filter and reduce.2
  • 2000 · October 16. Python 2.0: list comprehensions and a garbage collector that handles cycles.3
  • 2008 · December 3. Python 3.0 breaks compatibility on purpose: print becomes a function, text and bytes become different things, and integer division stops truncating.4 d/Python takes those three decisions as law.
  • 2013 · November. MicroPython is funded on Kickstarter: Python 3 on a microcontroller.5 d/Python's promises name it as a possible reference for how to build things, and explicitly not as the ceiling on compatibility.
  • 2020 · January 1 and October 5. Python 2 is retired; Python 3.9.0 ships.6 d/Python fixes its reference build, the CPython 3.9.6 build every test is checked against, by the hash of the executable, before accepting a single compiler feature.
  • 2026 · September 12. d/Python is introduced: Python 3 compiled to the d/OS bytecode, checked against that reference build, with a set of test programs that really run, windows and intents as Python calls, a playable game, and a browser playground built from the real compiler. What d/Python promises says what it must become; this site shows what it is today.

Python is a trademark of the Python Software Foundation. d/Python is a new implementation of the language and is not affiliated with or endorsed by the PSF; it contains no CPython and reuses only the RustPython parser, under its MIT notice. The licence details are in the FAQ.

What runs today, and what does not yet

d/Python is an initial, tested implementation of a broader set of promises. This site publishes what runs. The numbers were measured on the compiler and runtime you are about to use, and the full picture is on What Runs Today.

Built and running Where
The compiler: it parses Python, works out what the program means, turns it into bytecode, optimizes and checks it, and writes the compiled program file, .dbc, plus the shared library files, .dbl, each bound by hash this browser, macOS (dpython command line)
Integers of any size, Unicode strings and bytes, lists, tuples, dictionaries, sets, ranges, comprehensions, closures, classes with single inheritance, exceptions, with, modules and packages this browser, macOS; every row is supported in part, with a stated boundary
Console programs with interactive input(); window programs with open, draw, resize, key and pointer events; on-screen widgets through the shared UI engine this browser, a native window on macOS
The dos module: every callable intent, typed so it can be called from Python; fixed-size buffers, decimals, calls that return several results, calls into shared libraries this browser (without the parts of the host that supply files, sound or the network), macOS
Testing: 66 programs checked against the reference CPython 3.9.6 build, 416 tests passing, and the same test written in both d/BASIC and d/Python for the intents that have been exercised the repository, every build
Packaging: DPK2 packages with developer seals, resources and icons, through the same installer as d/BASIC the macOS command line, installer tests
Not yet, and said so Honest state
float arithmetic beyond writing a float literal, true division /, string repetition, .upper()/.lower(), open(), hashlib, contextlib, the standard library not yet supported; the compiler stops at the line and names each one
Generator functions and yield, async, descriptors, metaclasses, multiple inheritance, reflection, dynamic imports not yet supported
Collections that mix types, and/or whose result could be either type, changing a variable's type, empty containers before their element type is known the compiler explains why; what is missing is a way to carry a type tag with each value (the message calls it the tagged-value adapter)
Files, network and sound in the browser these work and are tested natively on macOS; this playground attaches no part of the host that supplies files, sound or the network, so such programs are declined before they start, with the reason named
Drag and drop, the pasteboard, messaging between programs (DOBJ), the DATA database and artifact rows every one can be called from Python, and none has been run in a test yet; this site does not teach them until it can prove them
Terminal input() on Linux and Windows, native window hosts there, and real d/OS hardware the compiler and runtime pass their tests on Linux and Windows, but the raw keyboard input path is macOS-only (on Linux, 65 of the 66 test programs pass; the one that calls input() is declined and says why) and window hosts exist only on macOS; the 8-bit machines are the platform's work, not the language's

One program, five places

Where What runs today
Your browser the compiler and runtime as WebAssembly: console programs, input(), windows, on-screen widgets, the game; this site's playground
macOS the dpython command line and a native window host; the kit with both programs, compiled examples and checks that it works from any folder
Linux and Windows the compiler, runtime and command line pass their test suites on both (test runs of 12 September 2026); the terminal input() path is still macOS-only, and native window hosts for these desktops are the next step; the browser build already runs there
Atari 8-bit, Commodore 64, Apple II the machines d/OS docks into with a cartridge coprocessor; d/Python produces the bytecode designed for them, and proof on the real hardware is the platform's to publish, not this site's
Small boards with a display the same runtime under the same window rules

d/Python is a house language of d/OS, an operating system that docks into the machines people already love and treats every screen as one composed picture. A d/Python program is a full d/OS application: it has a catalog entry, an icon, a window, a package format and a developer seal, with the same standing as a program written in d/BASIC, d/OS's other language. You do not need d/OS to use d/Python. You need a browser.

Learn it in human order

The guide is a course, not a wall of keywords. Every code block is one click from running.

The five ideas worth remembering

  1. It is Python 3. The rules come from the language reference and one fixed CPython build, not from whatever is convenient for the runtime.
  2. It is bytes. A program is a compiled .dbc file and the .dbl libraries it uses; no interpreter, no source and no CPython travel with it, and the same bytes run on every host.
  3. Partial is not complete. Every feature has a tested scope and a stated boundary; for the rest, the compiler stops at the line and says so.
  4. Types are inferred, and the compiler tells you when it cannot. A list holds one element type; an empty container needs a known shape before it is printed in a loop.
  5. Programs say what they want; hosts provide what they can. The dos module is the whole list of intents, typed for Python; a missing capability is a clear "no", never a fake.

  1. Guido van Rossum, Foreword for "Programming Python" (1st ed.), and History of Python

  2. History of Python: Version 1; 0.9.0 was posted to alt.sources on 20 February 1991. 

  3. What's New in Python 2.0, released 16 October 2000. 

  4. What's New in Python 3.0, released 3 December 2008. 

  5. MicroPython, Damien George's Kickstarter campaign of November 2013. 

  6. Python 3.9.0, 5 October 2020; Sunsetting Python 2, 1 January 2020.