- Use
#[pyclass]and#[pymethods]for Python-visible types. Use#[new]for constructors. - Map Rust
Result<T, E>to Python exceptions viaPyErr. UsePyResult<T>as return type. - Use
pyo3::typesfor conversions. Prefer&stroverStringin parameters, returnString. - Prefer
Bound<'py, T>overPy<T>for ergonomic, lifetime-checked references (PyO3 0.22+). - Release the GIL with
py.allow_threads()for CPU-intensive Rust code. Never hold GIL during I/O. - Use
#[getter]and#[setter]for properties. Implement__repr__and__str__for debugging. - Build with
maturin developfor local testing,maturin build --releasefor distribution. - Test bindings from Python using
pytest. Test both success and error paths. - Keep Python wrappers thin — business logic lives in Rust, Python provides ergonomic API.
- Anti-patterns:
.unwrap()in pyclass methods, blocking GIL for long operations, leaking Python objects.
Pyo3 Bindings
PyO3 conventions for exposing a Rust core to Python: pyclass/pymethods, PyErr/PyResult error mapping, GIL release, properties, maturin builds, and pytest. Load when generating or reviewing PyO3 Python bindings for a Rust library.
Pyo3 Bindings by goldziher · 5255a7e
npx skillmds@latest add goldziher/pyo3-bindings File contents
---name: pyo3-bindingsdescription: PyO3 conventions for exposing a Rust core to Python: pyclass/pymethods, PyErr/PyResult error mapping, GIL release, properties, maturin builds, and pytest. Load when generating or reviewing PyO3 Python bindings for a Rust library.---- Use `#[pyclass]` and `#[pymethods]` for Python-visible types. Use `#[new]` for constructors.- Map Rust `Result<T, E>` to Python exceptions via `PyErr`. Use `PyResult<T>` as return type.- Use `pyo3::types` for conversions. Prefer `&str` over `String` in parameters, return `String`.- Prefer `Bound<'py, T>` over `Py<T>` for ergonomic, lifetime-checked references (PyO3 0.22+).- Release the GIL with `py.allow_threads()` for CPU-intensive Rust code. Never hold GIL during I/O.- Use `#[getter]` and `#[setter]` for properties. Implement `__repr__` and `__str__` for debugging.- Build with `maturin develop` for local testing, `maturin build --release` for distribution.- Test bindings from Python using `pytest`. Test both success and error paths.- Keep Python wrappers thin — business logic lives in Rust, Python provides ergonomic API.- Anti-patterns: `.unwrap()` in pyclass methods, blocking GIL for long operations, leaking Python objects.
goldziher/ai-rulez/tree/main/internal/builtins/bindings/pyo3/skills/pyo3-bindings commit 5255a7ef50
Frequently asked questions
Run npx skillmds@latest add goldziher/pyo3-bindings in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
PyO3 conventions for exposing a Rust core to Python: pyclass/pymethods, PyErr/PyResult error mapping, GIL release, properties, maturin builds, and pytest. Load when generating or reviewing PyO3 Python bindings for a Rust library. It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
goldziher (@goldziher) published this skill. Their other Agent Skills are listed on their SkillMD profile.