Build high-performance Python extensions in Zig with automatic memory management.
Project description
pyz3 - Python Extensions in Zig
Write Python extensions in Zig. Fast builds, automatic type conversion, zero hassle.
Like PyO3 for Rust, but for Zig.
Get Started in 60 Seconds
pip install pyz3
pyz3 new myproject
cd myproject
pip install -e ".[dev]"
pyz3 develop
pytest
That's it. You now have a working Python extension written in Zig.
Try it:
>>> from myproject import _lib
>>> _lib.add(2, 3)
5
>>> _lib.hello("pyz3")
'Hello, pyz3!'
What You Get
myproject/
src/myproject.zig # Your Zig code (auto-converts to Python module)
myproject/__init__.py # Python package
test/test_myproject.py # Tests that work with pytest
pyproject.toml # Standard Python packaging (hatchling)
build.zig.zon # Zig package manifest
Write Zig, Call from Python
Functions
const py = @import("pyz3");
/// Exposed as a Python function with automatic type conversion.
pub fn add(args: struct { a: i64, b: i64 }) i64 {
return args.a + args.b;
}
comptime {
py.rootmodule(@This());
}
>>> import mymodule
>>> mymodule.add(a=2, b=3) # keyword args work too
5
Classes
pub const Counter = py.class(struct {
pub const __doc__ = "A simple counter.";
const Self = @This();
value: i64,
pub fn __init__(self: *Self, args: struct { start: i64 = 0 }) void {
self.value = args.start;
}
pub fn increment(self: *Self) void {
self.value += 1;
}
pub fn get(self: *const Self) i64 {
return self.value;
}
});
>>> c = mymodule.Counter(start=10)
>>> c.increment()
>>> c.get()
11
Error Handling
pub fn divide(args: struct { a: i64, b: i64 }) !i64 {
if (args.b == 0) {
return py.ZeroDivisionError(root).raise("division by zero");
}
return @divTrunc(args.a, args.b);
}
NumPy Integration
pub fn array_stats() !py.PyObject {
const np = try py.numpy.getModule(@This());
defer np.decref();
const arange_method = try np.getAttribute("arange");
defer arange_method.decref();
const arr = try py.call(root, py.PyObject, arange_method, .{ 1, 11 }, .{});
defer arr.decref();
const mean_method = try arr.getAttribute("mean");
defer mean_method.decref();
return try py.call(root, py.PyObject, mean_method, .{}, .{});
}
Type Conversion
Automatic conversion between Python and Zig types:
| Zig Type | Python Type |
|---|---|
bool |
bool |
i32, i64, u64 |
int |
f32, f64 |
float |
[]const u8 |
str |
struct {...} |
keyword args / dict |
py.PyObject |
any Python object |
!T |
raises Python exception on error |
CLI Commands
pyz3 new <name> # Create new project
pyz3 develop # Build + install in dev mode
pyz3 run -c "expr" # Build + run a Python expression
pyz3 run script.py # Build + run a script
pyz3 watch # Hot-reload on file changes
pyz3 build-wheel # Build distribution wheel
pyz3 deploy # Publish to PyPI
pyz3 bench <module> # Run benchmarks
pyz3 stubs <module> # Generate .pyi type stubs
pyz3 memcheck script.py # Memory leak detection
Compatibility
- Zig: 0.15.x
- Python: 3.11, 3.12, 3.13 (CPython)
- Platforms: Linux (x86_64, aarch64), macOS (x86_64, arm64), Windows (x64)
Installation
pip install pyz3
With distribution extras:
pip install pyz3[dist]
Cross-Platform Distribution
# Build for all platforms
pyz3 build-wheel --all-platforms
# Or target specific platforms
ZIG_TARGET=x86_64-linux-gnu pyz3 build-wheel
ZIG_TARGET=aarch64-macos pyz3 build-wheel
Why pyz3?
- Fast builds — Zig compiles faster than Rust, comparable to C
- Zero-cost abstractions — No runtime overhead from the bridge
- Cross-compile everything — Zig's cross-compilation makes multi-platform wheels trivial
- Small binaries — Smaller than equivalent Rust/PyO3 extensions
- SIMD for free — Zig's auto-vectorization and explicit SIMD support
- C interop included — Import any C library with
@cImport
Acknowledgments
Hard fork of ziggy-pydust by Fulcrum. Major additions: NumPy integration, enhanced CLI, cross-compilation, improved docs.
License
Apache License 2.0
Links
- ziggy-pydust (original project)
- Zig | NumPy | PyO3 (inspiration)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyz3-0.11.0-py3-none-any.whl.
File metadata
- Download URL: pyz3-0.11.0-py3-none-any.whl
- Upload date:
- Size: 283.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b31fa0e7797e99826d232cb96cb830a75bc887ddb210566a9d254d661cdfc86f
|
|
| MD5 |
ee26c2e42e3091faa3a7b44e7cac8e93
|
|
| BLAKE2b-256 |
b7716eea9dc7b0b9bd21a3f76045cd7ba33785f249d47a1fb32550a5d45dd64a
|
Provenance
The following attestation bundles were made for pyz3-0.11.0-py3-none-any.whl:
Publisher:
build-wheels.yml on plutonium-guy/pyz3
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyz3-0.11.0-py3-none-any.whl -
Subject digest:
b31fa0e7797e99826d232cb96cb830a75bc887ddb210566a9d254d661cdfc86f - Sigstore transparency entry: 1282843767
- Sigstore integration time:
-
Permalink:
plutonium-guy/pyz3@b98908b1e5d9b97017bf44f8b786cd473b21a988 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/plutonium-guy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-wheels.yml@b98908b1e5d9b97017bf44f8b786cd473b21a988 -
Trigger Event:
push
-
Statement type: