Skip to main content

pyz3 - Python Extensions in Zig

Write Python extensions in Zig. Fast builds, automatic type conversion, zero hassle.

Like PyO3 for Rust, but for Zig.

Package version Python version License


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

Metadata

Release files for pyz3 0.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for pyz3 0.11.0
File Interpreter ABI Platform
pyz3-0.11.0-py3-none-any.whl Python 3 none any Details

Release files / pyz3-0.11.0-py3-none-any.whl

Download URL pyz3-0.11.0-py3-none-any.whl
Size 283.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b31fa0e7797e99826d232cb96cb830a75bc887ddb210566a9d254d661cdfc86f
BLAKE2b-256 checksum
How to use checksums
b7716eea9dc7b0b9bd21a3f76045cd7ba33785f249d47a1fb32550a5d45dd64a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.11.0 This release

1 release file

0.10.2

1 release file

0.10.1

1 release file

0.10.0

1 release file

0.9.2

1 release file

0.9.1

1 release file

0.9.0

1 release file

0.8.0

1 release file

0.7.0

1 release file

0.6.0

1 release file

0.5.0

1 release file

0.3.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page