A runtime for executing CPython compiled to WebAssembly/WASI with an in-memory virtual filesystem and socket support.
Built as a lark, I'm not realy sure what it would be useful for but I spent a few days on it so it might as well be public.
============================================================
zig-wasm-cpython Test Script
============================================================
Python version: 3.13.1 (tags/v3.13.1-dirty:0671451, Jan 1 2026, 00:53:23) [Clang 18.1.2-wasi-sdk (https://github.com/llvm/llvm-project 26a1d6601d727a96f43
Platform: wasi
Testing JSON module:
{
"message": "Hello from Python in WASM!",
"features": [
"VFS",
"Sockets",
"Standard Library"
],
"status": "working"
}
Testing Python features:
Squares: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Testing raw socket with HTTP request:
✓ Socket created
✓ Connected to example.com:80
✓ Sending 56 byte request...
Sent 32 bytes
Sent 24 bytes
✓ Request sent successfully
✓ Receiving response...
✓ HTTP Response: HTTP/1.1 200 OK
✓ Received 823 bytes
<!doctype html><html lang="en"><head><title>Example Domain</title><meta name="viewport" con...
============================================================
All tests passed! ✅
============================================================
- In-Memory VFS: Run Python scripts from memory without touching the filesystem
- Python Standard Library: Full access to Python's standard library via VFS
- Socket Support: Custom WASI socket implementation for network I/O
- HTTP Requests: Full support for
requestslibrary with HTTP (HTTPS requires TLS) - Bytecode Libraries: Support for pre-compiled Python bytecode packages (e.g., requests, urllib3, impacket)
- Command-line Interface: Run arbitrary Python scripts with a simple CLI
- Zig 0.15.2 or later
- CPython WASM binary (included:
src/examples/python-wasi.wasm)
zig build -Doptimize=ReleaseFastRun the default requests test script:
./zig-out/bin/zig_wasm_cpython --script ./examples/demo_requests.pyRun your own Python script:
./ig-out/bin/zig_wasm_cpython --script path/to/your/script.py--script, -s <path>- Run a Python script from the host filesystem--help, -h- Show help message
-
VFS (Virtual File System) - In-memory filesystem for Python scripts and libraries
- Located in
src/vfs/ - Supports files, directories, and passthrough to real filesystem
- WASI-compatible interface
- Located in
-
WASI Handlers - WebAssembly System Interface implementations
- Located in
src/wasi/ - Bridges between zware runtime and VFS
- Full
fd_*andpath_*function support
- Located in
-
Basic Socket Support - Network I/O for Python
- Located in
src/sockets/ - Custom WASI socket implementation
- Python c extension module
_wasisocket
- Located in
-
Python Environment - Configuration and initialization
- Located in
src/python/ - Environment variable setup
- Standard library loader
- Bytecode library support
- Located in
- Initialization: VFS is created and populated with Python stdlib and custom scripts
- WASM Loading: CPython WASM binary is loaded via zware
- Environment Setup: Python paths and environment variables are configured
- Execution: Python interpreter is initialized and runs the target script
- Cleanup: Resources are freed and Python is finalized
The runtime includes Python 3.13's standard library, loaded into in-memory VFS.
Pre-compiled Python bytecode libraries can be included for faster loading and reduced memory footprint. The included example demonstrates requests support.
To compile your own bytecode libraries:
python3 compile_library.py path/to/package output_dirNetwork I/O is supported through a custom _wasisocket C extension module. Example:
import socket
# Standard Python socket API works!
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("example.com", 80))
s.send(b"GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
response = s.recv(4096)
s.close()The popular requests library is partially supported for HTTP operations:
import requests
# HTTP GET (disable compression since zlib not available)
headers = {'Accept-Encoding': 'identity'}
response = requests.get('http://example.com', headers=headers, timeout=10)
print(response.text)
# HTTP POST with JSON
payload = {'message': 'Hello from WASM!'}
response = requests.post('http://httpbin.org/post', json=payload, headers=headers)
print(response.json())Note: HTTPS is not yet supported as it requires TLS implementation at the host layer. Compression (gzip/deflate) is disabled as zlib is not available in WASM.
- Building CPython WASM - How to build the CPython WASM binary
- Socket API - Details on socket implementation
- Bytecode Libraries - How to use pre-compiled bytecode
- Architecture Details - Deep dive into code organization
- Development Notes - Historical development information
├── src/
│ ├── main.zig # Entry point and orchestration
│ ├── examples/
│ │ ├── python-wasi.wasm # CPython WASM binary
│ │ └── python/ # Example Python scripts
│ ├── vfs/ # Virtual filesystem
│ ├── wasi/ # WASI handlers
│ ├── sockets/ # Socket implementation
│ ├── python/ # Python environment setup
│ └── python_extensions/ # C extension modules
├── compiled_libs/ # Pre-compiled bytecode libraries
├── python_libs/ # Source Python libraries
├── docs/ # Documentation
├── build.zig # Build configuration
└── README.md # This file
- zware - WebAssembly runtime for Zig
- CPython 3.13 compiled to WASI (included)
If you need to rebuild the CPython WASM binary (e.g., to add more C extensions), see docs/BUILDING_CPYTHON.md.
- No HTTPS/TLS: HTTPS is not supported as WASI lacks TLS support
- No compression: zlib is not available, so gzip/deflate compression is disabled
- No ctypes/FFI: libffi cannot be compiled to WASM/WASI, so ctypes is not available (no impacket :( )
- No threading: WASI has no threading support (at least as implemented here)
- No dynamic loading: C extensions must be compiled into the WASM binary
If this interests you, go contribute WASI support upstream zware
This projects code is WTFPL, see respective dependent libraries for real license info if you really care.
This project builds upon:
- CPython (Python Software Foundation License)
- zware (MIT License)
- WASI SDK (Apache License 2.0)
See individual components for their respective licenses.