Skip to main content

Build high-performance Python extensions in Zig with automatic memory management. Inspired by ziggy-pydust.

Project description

pyz3 - Python Extensions in Zig

A high-performance framework for writing Python extension modules in Zig with automatic memory management, hot-reload, and NumPy integration.

🌟 Inspired by ziggy-pydust

Actions Package version Python version License


Documentation: https://github.com/amiyamandal-dev/pyz3

Source Code: https://github.com/amiyamandal-dev/pyz3


Overview

pyz3 is a complete framework for building high-performance Python extension modules in Zig. It provides:

  • 🚀 Seamless Python-Zig Interop - Automatic argument marshalling and type conversion
  • 📊 NumPy Integration - Zero-copy array access with type-safe dtype mapping
  • 🔧 Complete CLI Toolkit - Maturin-style commands for project lifecycle management
  • 📦 Cross-Platform Builds - Build wheels for Linux, macOS, and Windows
  • 🔗 C/C++ Integration - Automatic binding generation for C/C++ libraries
  • 🧪 Testing Integration - Pytest plugin to discover and run Zig tests
  • Hot Reload - Watch mode with automatic rebuilding
  • 🛡️ Memory Safe - Leverages Zig's safety features with Python's GC

Quick Example

const py = @import("pyz3");

pub fn fibonacci(args: struct { n: u64 }) u64 {
    if (args.n < 2) return args.n;

    var sum: u64 = 0;
    var last: u64 = 0;
    var curr: u64 = 1;
    for (1..args.n) |_| {
        sum = last + curr;
        last = curr;
        curr = sum;
    }
    return sum;
}

comptime {
    py.rootmodule(@This());
}
import mymodule
print(mymodule.fibonacci(10))  # Output: 55

NumPy Integration Example

const py = @import("pyz3");

pub fn double_array(args: struct { arr: py.PyArray(@This()) }) !py.PyArray(@This()) {
    // Zero-copy access to NumPy array
    const data = try args.arr.asSliceMut(f64);

    for (data) |*val| {
        val.* *= 2.0;
    }

    return args.arr;
}

comptime {
    py.rootmodule(@This());
}
import numpy as np
import mymodule

arr = np.array([1.0, 2.0, 3.0])
result = mymodule.double_array(arr)
print(result)  # Output: [2.0, 4.0, 6.0]

Compatibility

  • Zig: 0.15.x (tested with 0.15.2)
  • Python: 3.11+ (CPython)
  • Platforms: Linux (x86_64, aarch64), macOS (x86_64, arm64), Windows (x64)

Installation

pip install pyz3

Or with distribution extras for building wheels:

pip install pyz3[dist]

Quick Start

1. Create a New Project

# Create project using cookiecutter template
pyz3 init -n myproject --description "My awesome extension" --email "you@example.com" --no-interactive

cd myproject

2. Build Your Extension

# Development build
zig build

# Release build
zig build -Doptimize=ReleaseFast

# Watch mode (hot reload)
pyz3 watch

3. Test Your Extension

# Run pytest
pytest

# Run specific test
pytest test/test_myproject.py -v

4. Package for Distribution

# Build wheel for current platform
python -m build --wheel

# Build for all platforms (uses cross-compilation)
pyz3 build-wheel --all-platforms

# Publish to PyPI
pyz3 deploy --repository testpypi  # Test first!
pyz3 deploy --repository pypi       # Production

CLI Commands

pyz3 provides a complete CLI for managing your extension projects:

pyz3 init [OPTIONS]           # Initialize new project
pyz3 build [OPTIONS]          # Build extension module
pyz3 watch                    # Watch mode with hot reload
pyz3 test [OPTIONS]           # Run tests
pyz3 clean                    # Clean build artifacts
pyz3 build-wheel [OPTIONS]        # Build distribution packages
pyz3 deploy [OPTIONS]        # Publish to PyPI

Key Features

Type-Safe Python-Zig Bridge

Automatic conversion between Python and Zig types:

Zig Type Python Type
void None
bool bool
i32, i64 int
f32, f64 float
[]const u8 str
struct {...} dict
py.PyArray(root) numpy.ndarray

Classes and Methods

pub const Point = py.class(struct {
    pub const __doc__ = "A 2D point";
    const Self = @This();

    x: f64,
    y: f64,

    pub fn __init__(self: *Self, args: struct { x: f64, y: f64 }) !void {
        self.* = .{ .x = args.x, .y = args.y };
    }

    pub fn distance(self: *const Self) f64 {
        return @sqrt(self.x * self.x + self.y * self.y);
    }
});

Exception 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);
}

Cross-Platform Distribution

Build wheels for multiple platforms:

# Using environment variables
ZIG_TARGET=x86_64-linux-gnu PYZ3_OPTIMIZE=ReleaseFast python -m build --wheel
ZIG_TARGET=aarch64-linux-gnu PYZ3_OPTIMIZE=ReleaseFast python -m build --wheel
ZIG_TARGET=x86_64-macos PYZ3_OPTIMIZE=ReleaseFast python -m build --wheel
ZIG_TARGET=aarch64-macos PYZ3_OPTIMIZE=ReleaseFast python -m build --wheel
ZIG_TARGET=x86_64-windows-gnu PYZ3_OPTIMIZE=ReleaseFast python -m build --wheel

The build system automatically:

  • Detects target platform
  • Cross-compiles for different architectures
  • Creates manylinux-compatible wheels
  • Handles platform-specific optimizations

Performance

pyz3 leverages Zig's performance advantages:

  • Zero-cost abstractions - No runtime overhead
  • Compile-time optimizations - Zig's comptime for metaprogramming
  • SIMD support - Automatic vectorization where possible
  • Small binaries - Smaller than equivalent Rust extensions
  • Fast compilation - Faster than Rust, comparable to C

Acknowledgments

This project is a hard fork of ziggy-pydust by Fulcrum.

Major differences in pyz3:

  • ✅ Built-in NumPy integration with zero-copy array access
  • ✅ Enhanced cross-compilation support
  • ✅ Updated CLI commands and workflows
  • ✅ Comprehensive NumPy examples and tests
  • ✅ Improved documentation for data science use cases

Special thanks to the original ziggy-pydust contributors for creating an excellent foundation!

License

Apache License 2.0

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyz3-0.6.0-py3-none-any.whl (204.1 kB view details)

Uploaded Python 3

File details

Details for the file pyz3-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: pyz3-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 204.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyz3-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 afdfeca1d53a5a64e35a6fd71b4fe1c75bdcf6cc5d747a87abdad61224c48cd3
MD5 1fa93a319ff75c0723e752cb23fd49a5
BLAKE2b-256 e31851539d5d9421e17c705d9a01beba423daaee78197c93804d24315f0c8542

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyz3-0.6.0-py3-none-any.whl:

Publisher: build-wheels.yml on amiyamandal-dev/pyz3

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page