Python v2 logo — two snakes, red and blue python™v2
▶ Subscribe

Documentation

Everything you need to get Python v2 running: on your desktop, in VS Code, in a dev container or Codespaces, or in any code editor you already love. Then the whole language and PyHope game engine, on one page. Want more? Read the 50-topic field guide. New to Python v2? Start the tutorial — or open the dual-runtime Playground for commands, errors, and website templates.

01 Install — Desktop

Python v2 has no dependencies and no install step. If you have Python 3.10+ and Git, you're done. Works on macOS, Linux, Windows (native or WSL), and a fridge with a shell.

Step 1 — check Python
python3 --version    # need 3.10 or newer
git --version
Step 2 — get the runtime
git clone https://github.com/gefrus112/pythonv2
cd pythonv2
Step 3 — verify it works
python3 -m pyv2 --version
# Python v2 1.1.0

python3 -m pyv2 examples/hello.pyv2
# Hello, World!
# 2 + 2 = 4
Step 4 — run the test suite (optional, 1 second)
python3 -m unittest discover -s tests -t .
# ... OK

Command line

CommandWhat it does
python3 -m pyv2 script.pyv2Run a program
python3 -m pyv2 -c 'print(42)'Run a one-liner
python3 -m pyv2Start the REPL (... continues blocks)
python3 -m pyv2 --versionPrint the version
python3 -m pyv2 --helpShow usage

Windows notes

02 VS Code

The repository ships ready-made VS Code config in .vscode/ and a language extension in editors/vscode/ for syntax highlighting of .pyv2 files.

Quick start (run & debug your code)

  1. Open the pythonv2 folder in VS Code (File → Open Folder…).
  2. Open any .pyv2 file, e.g. examples/fib.pyv2.
  3. Press Ctrl+Shift+B (macOS: Cmd+Shift+B) — the default build task runs python3 -m pyv2 on the current file.
  4. Output appears in the Terminal panel. That's it.

The included .vscode/tasks.json defines two tasks: Run Python v2 file (default build) and Python v2 REPL. The included .vscode/settings.json associates *.pyv2 with the pyv2 language.

Syntax highlighting (the bundled extension)

  1. Copy the extension folder into your VS Code extensions directory:
    # macOS / Linux
    cp -r editors/vscode ~/.vscode/extensions/pyv2-0.1.0
    
    # Windows (PowerShell)
    Copy-Item -Recurse editors/vscode "$env:USERPROFILE\.vscode\extensions\pyv2-0.1.0"
  2. Restart VS Code (or run Developer: Reload Window).
  3. Open any .pyv2 file — keywords, strings, f-strings, numbers and comments are now colored.

Prefer the marketplace workflow? Pack it once with the vsce tool and install the VSIX:

cd editors/vscode
npx @vscode/vsce package        # builds pyv2-0.1.0.vsix
code --install-extension pyv2-0.1.0.vsix

Alternative: Code Runner

If you use the popular Code Runner extension, add this to your user settings.json and press Ctrl+Alt+N to run:

{
  "code-runner.executorMap": {
    "python": "python3 -m pyv2"
  },
  "code-runner.fileDirectoryAsCwd": true
}

03 Dev Containers & GitHub Codespaces

Opening the repo in a dev container (VS Code or Codespaces) gives you a ready environment in seconds — Python preinstalled, tasks wired, tests passing. The config lives in .devcontainer/devcontainer.json (that's the ".dev" part).

VS Code Dev Containers

  1. Install Docker and the Dev Containers extension (ms-vscode-remote.remote-containers).
  2. Open the repo folder, then run Dev Containers: Reopen in Container from the Command Palette (Ctrl+Shift+P).
  3. First boot pulls the Python image; after that everything is instant.
  4. Run python3 -m pyv2 examples/hello.pyv2 — or just hit Ctrl+Shift+B.

GitHub Codespaces

  1. On GitHub, open the repo → Code → Codespaces → Create codespace on main.
  2. VS Code opens in your browser with the dev container already built.
  3. Everything from the desktop guide works identically inside it.

The container runs python3 -m unittest discover -s tests -t . at build time, so you always start from a green suite.

04 Any Other Code Editor

Python v2 is just text plus a CLI. Any editor that can run a shell command can run it. The universal recipe:

Sublime Text

Tools → Build System → New Build System…
{
    "cmd": ["python3", "-m", "pyv2", "$file"],
    "selector": "source.python",
    "working_dir": "$file_path"
}

Vim / Neovim

" in init.vim / .vimrc
autocmd BufNewFile,BufRead *.pyv2 set filetype=python
autocmd FileType python nnoremap <F5> :w<CR>:!
    \python3 -m pyv2 %<CR>

JetBrains (PyCharm, IntelliJ)

  1. Settings → Editor → File Types → add *.pyv2 to the Python type.
  2. Settings → Tools → External Tools → add a tool with program python3, arguments -m pyv2 $FileName$, working directory $FileDir$.
  3. Bind it to a shortcut under Settings → Keymap.

Notepad++

Run → Run… (F5) with:

cmd /c python3 -m pyv2 "$(FULL_CURRENT_PATH)"

05 Browser Playground

Open the Playground to edit and run code without installing anything. It has line numbers, starter programs, keyboard execution, command history, and separate Output and Problems terminals so runtime errors never get mixed into normal program output.

ModeWhat runsUse it for
Python v2The complete pyv2.js browser runtimeLanguage programs, game data, and website templates
Classic PythonA documented compatibility subset translated locally to Python v2def, indentation, variables, loops, lists, maps, functions, and print
Local CPythonNot embedded in the static websiteImports, packages, native extensions, files, and the full standard library
Run code and commands
  1. Choose Python v2 or Classic compatibility.
  2. Pick a starter, edit the source, and press Ctrl+Enter.
  3. Read normal text in Output and failures in Problems.
  4. Use the bottom prompt for expressions and assignments. Commands :help, :clear, :reset, and :mode classic are built in.

The Portfolio Starter uses editable Python v2 maps and lists for your profile, role, biography, skills, statistics, projects, games, location, and contact details. Valid edits live-sync into a responsive preview. Switch to HTML Code to inspect or copy the exact generated document, then download it as a standalone page. The desktop New Project tool creates the richer multi-file offline version.

06 Python v2 + PyHope Workspace

Python v2 1.1 ships with its own desktop workspace. It is implemented with Python's standard-library tkinter toolkit—no Electron, pygame, browser shell, subscription, or account.

Open the app

# after running install.bat or install.sh, either command opens the workspace:
pyhope-studio
pyv2-launcher

# the PyHope CLI can launch it too:
pyhope --studio

# always works, even if the command folder is not on PATH:
python3 -m pyv2.launcher

Windows also gets a Desktop shortcut. macOS gets ~/Applications/Python v2 Sudbury.app. Linux gets an app menu entry. If your Linux distribution separates tkinter, install its python3-tk package; the language CLI still works without it.

App layout

AreaWhat it does
HomeWorkspace overview and shortcuts to every main tool
Code StudioOpen, edit, save, and run .pyv2; output/errors stay in the app
FilesSafe local workspace service: create, read, atomically save, rename, and delete files without path traversal
New ProjectCreate Website, Windows app, CLI app, or Game starters without overwriting files
AssetsBrowse and export eight packaged original CC0 PyHope SVGs offline
Games & GPUOpen the 10-game arcade, animated sprites, and 9M GPU Lab
Connected EditorsDetect VS Code, VSCodium, Zed, Sublime Text, and PyCharm from PATH; no account or token
SettingsWorkspace folder, preferred editor, code font size, and run autosave
Docs & LearnPlayground, tutorial, 50-topic guide, reference, and CubeCometYT milestone
DonationComing soon—the app does not collect money or payment data

Build a website with Python v2

  1. Open New Project and choose Website.
  2. The Launcher creates app.pyv2, index.html, runner.js, an offline copy of pyv2.js, and ready-to-run .vscode tasks/settings.
  3. Edit app.pyv2. Its structured output fills the profile, skills, project cards, featured games, and contact section.
  4. Choose local preview. The Launcher starts a safe local HTTP server on an available port and opens your responsive portfolio.
# app.pyv2 — one record becomes one part of the page
profile = {name: "Alex", role: "Creative developer"}
skills = ["Python v2", "PyHope", "Web design"]
print("PROFILE|" + profile.name + "|" + profile.role + "|I build playful tools.")
print("ABOUT|My personal biography goes here.")
for skill in skills:
    print("SKILL|" + skill)
end
print("GAME|Comet Circuit|Racing|Three-lap AI racing.|games.html#comet-circuit")

07 Production Apps & Windows EXE Builder

Sudbury Build Tools turn a .pyv2 program into a validated, inspectable application project and—when the native build runs on Windows—a real one-file .exe. Python v2 does not rename a Linux or macOS binary and pretend it is a Windows executable.

Create, run, check, and build

# Complete console application with JSON persistence
pyv2 new windows-app "Comet Tasks"

# Or create a dialog-based app with no terminal window
pyv2 new windows-app "Hello Window" --windowed

pyv2 Comet-Tasks/main.pyv2 --add "Ship the EXE"
pyv2 check Comet-Tasks
pyv2 build Comet-Tasks

# Run this final command on Windows with PyInstaller installed.
# The generated build-windows.bat handles that installation for you.
pyv2 build Comet-Tasks --native
Generated filePurpose
main.pyv2Readable application source using arguments, strict JSON, and persistent app data
pyv2app.jsonName, stable app ID, version, publisher, console/windowed mode, icon, and assets
build-windows.batValidates and builds the real EXE on Windows without administrator access
.github/workflows/windows-exe.ymlOptional Windows CI build and downloadable executable artifact
build/windows/manifest.jsonSHA-256 source and build-input integrity record
runtime/pyv2Exact vendored language runtime used for the build—no moving runtime dependency
app.spec + launcher.pyReviewable PyInstaller recipe and embedded Python v2 host

Application APIs

info = app_info()                  # name, version, platform, safe data directory
commands = args()                  # values after the .pyv2 filename / EXE
settings = {theme: "night", zoom: 1.25}
write_text("settings.json", json_encode(settings))
loaded = json_decode(read_text("settings.json"))
print(loaded.theme)

# Other safe services:
# append_text, file_exists, list_dir, make_dir, delete_file
# read_asset, asset_exists, sleep_ms, ui_message, ui_ask

During development, writable data stays in .pyv2-data/ beside the program. Packaged apps use %LOCALAPPDATA%\PythonV2Apps\APP-ID. Paths are relative and sandboxed; atomic writes, UTF-8 validation, an 8 MB text limit, asset size validation, symlink-escape checks, and unmanaged-build-directory protection are enabled by default.

Building from macOS or Linux: pyv2 build still creates the complete Windows kit. Copy it to Windows and run build.bat, or push the generated project and run its GitHub Actions workflow on a Windows runner. PyInstaller cannot cross-compile Windows PE files from another operating system.

Signing note: generated executables are reproducible but not Authenticode-signed automatically. Public distributors should add their own protected code-signing certificate in Windows CI; never commit a certificate or password to the project.

08 PyHope Game Engine

PyHope is Python v2's own dependency-free game engine. It is not pygame and it installs no native libraries. The portable Python module handles game logic and terminal previews; the website adds Canvas and WebGL2 renderers for full visual games.

Install and verify

# one-click: download install.bat (Windows) or install.sh (macOS/Linux)
# manual, from the cloned repo:
python3 -m pip install --user .

pyv2 --version
pyhope --check
pyhope --demo

Download the installers. The installer adds both commands and runs the check automatically.

Core API

APIPurposeExample
Vec2Immutable 2D vectors, length, normalize, dot productVec2(3, 4).normalized()
SpriteNamed entity with position, velocity, tags and alive stateSprite("hero", Vec2(2, 2), "@")
TileMapRectangular collision map; dots/spaces are walkableTileMap.from_text(level)
EngineFixed-step scene, systems, movement and collisionEngine(world, tick_rate=60)
raycastFast grid DDA ray casting with hit distance and wall sideraycast(world, origin, direction)
render_asciiDependency-free terminal scene previewprint(engine.render_ascii())
Canvas renderer10 games: shooting, platform physics, racing, grid and brick arcade modesPlay arcade
WebGL2 renderer1280×720 live / 4096×2304 9M frameOpen GPU lab

Your first PyHope scene

from pyhope import Engine, Sprite, TileMap, Vec2

world = TileMap.from_text("""#####
#...#
#...#
#####""")
engine = Engine(world)
hero = engine.add(Sprite("hero", Vec2(1.5, 1.5), "@"))
hero.velocity = Vec2(0.5, 0)
engine.step()
print(engine.render_ascii())

The visual examples are open source: game.js is the CPU sprite raycaster, gpu-game.js is the 9M renderer, and games.js contains Comet Hopper. Original sprites are CC0 in assets/sprites/.

09 Language Quick Reference

The full spec (grammar, semantics, error kinds) lives in docs/LANGUAGE.md. Here is the day-to-day core.

Values

TypeExampleNotes
number1, 2.5, 1e-3Whole numbers print without .0
string"hi", f"hi {x}"Indexed s[0], tons of methods
booltrue, false
nilnilAbsence of a value
list[1, 2, 3]Mutable; negative indices work
map{name: "Ada"}Bare keys, dot access, get(k, default)
fnfn add(a, b): … endFirst-class, real closures
rangerange(10)Lazy, from the range builtin

Operators

KindOperators
Arithmetic+ - * / // % **
Comparison== != < <= > >=
Logicand, or, not
Membershipx in list, k in map, s in string
Ternaryok ? "yes" : "no"
Assignment= += -= *= /= %=

Statements

StatementExample
functionfn add(a, b): return a + b end
branchif x: … elif y: … else: … end
whilewhile running: step() end
forfor item in [1, 2, 3]: print(item) end
range loopfor i in range(1, 10, 2): print(i) end
recovertry: risky() catch error: print(error.kind) finally: cleanup() end
raiseraise {kind: "ConfigError", message: "port required"}
jumpreturn, break, continue

Structured error recovery

Runtime errors are catchable values. A named catch receives a map with kind, message, line, and trace. The optional finally block always runs, including during return, break, and continue.

try:
    result = 100 / divisor
catch error:
    print(error.kind + ":", error.message)
    result = 0
finally:
    print("calculation complete")
end

raise "message" creates a UserError. Raise a map with string kind and message fields to create a named application error. Syntax errors are detected before execution and are not catchable.

Builtins

FunctionDescription
print(...)Print values, space-separated
len(x)Length of string / list / map / range
range(stop) · range(a, b, step)Integer range
sum · enumerate · zipIterable aggregation and pairing
all · anyTruth tests across an iterable
str int float bool reprConversions
abs floor ceil round sqrt powMath
min · maxOver arguments or one list
type(x)"number", "string", "list", "map", …
push pop insert removeList mutation
keys values has getMap access
sort sort_by joinHelpers
assert(cond, msg?)Raises AssertionError when falsy
json_encode json_decodeStrict JSON for persistent application data
args app_infoApplication arguments, identity, platform, and capability details
read_text write_text append_textSandboxed UTF-8 files with atomic replacement
file_exists list_dir make_dir delete_fileSafe app-data management
read_asset asset_exists ui_message ui_askPackaged assets and native dialogs
chr ord clock input sleep_msCharacters, timing, and desktop input

10 Try It Right Here

No install needed to experiment — this is the real interpreter, running in your browser. Edit and hit Run.