Scaling PyO3 down with single-file Python extensions
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 680
- Forks
- 110
- Avg merge
- 3d 18h
- Merged PRs (30d)
- 1
Description
One nice thing about Cython is that you can have a single .pyx file, two lines in setup.py and one line in requirements.txt, and you're good. With PyO3, you need a Cargo.toml, configured a particular way (cdylib), and so it's just a bit more ceremony than Cython for simple cases.
Maturin is great for standalone libraries, but doesn't help simplify the case of adding a quick extension to an existing Python project.
To solve this, one could imagine single-file Rust extension modules, inspired by https://github.com/rust-lang/rfcs/blob/master/text/3424-cargo-script.md (and see the references to existing tools that predate the RFC, mostly for executables). You might then have:
setup.py
mypackage/
__init__.py
module.py
_extension.rs
And the setup.py is modified to point at _extension.rs, much like you would with Cython, rather than pointing at Cargo.toml as it normally does:
from setuptools import setup
from setuptools_rust import Binding, RustSingleFileExtension
setup(
name="mypackage",
version="1.0",
rust_extensions=[RustSingleFileExtension("mypackage._extension", binding=Binding.PyO3)],
packages=["mypackage"],
# rust extensions are not zip safe, just like C-extensions.
zip_safe=False,
)
The _extension.rs might look like this:
//! ```cargo
//! [dependencies]
//! pyo3 = "0.19"
//! ```
use pyo3::prelude::*;
/// Formats the sum of two numbers as string.
#[pyfunction]
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
Ok((a + b).to_string())
}
/// A Python module implemented in Rust.
#[pymodule]
fn _extension(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
Ok(())
}
Once you start thinking about lock files this starts getting more complicated, they could be auto-generated as mypackage/_extension.rs.lock, and you'd need some way to update them... conceivably could outsource that to Cargo eventually if the feature becomes non-experimental and they are willing to add a new use case.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the proposed setup.py integration around RustSingleFileExtension and compare it with the existing Cargo.toml-based flow. Review the linked Cargo script RFC and its prior art, then investigate how PyO3 dependencies and the proposed .rs.lock files would be handled. Done would mean a defined, maintainable approach for building a single-file Rust extension in an existing Python package.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- build-system
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100