Sometimes systems have a proprietary legacy that is not possible to port to newer versions of languages. But people still need to work, systems using python 2 still have to be written.
This project is a fork of an old version of pyo3 that supported python2, with some patches to please newer Rust compilers.
- DO NOT use python 2 in 2025
- Really, DO NOT use python 2 in 2025
- Use this project only as a last resort
- ???
- Rewrite everything to support modern languages.
- Original issue about removing python 2 support: PyO3#138
- The Statement
I doubt I ever publish it to crates, so you just need to use git directly:
[dependencies]
pyo3 = { git = "git@github.com:nev3rfail/pyo3-py2.git", branch = "py2", features = ["python2"] }
Currently only the code under the python2 feature flag has been modified to compile, so patches are welcome. For now i'm just patching whatever I personally need and not touching the other parts of the codebase, but it is theoretically possible to backport this into relevant versions of pyo3, or maybe even glue py2 support as a library.
Rust bindings for Python. This includes running and interacting with python code from a rust binaries as well as writing native python modules.
A comparison with rust-cpython can be found in the guide.
Pyo3 supports python 2.7 as well as python 3.5 and up. The minimum required rust version is 1.30.0-nightly 2018-08-18.
You can either write a native python module in rust or use python from a rust binary.
Pyo3 can be used to generate a native python module.
Cargo.toml
:
[package]
name = "string-sum"
version = "0.1.0"
[lib]
name = "string_sum"
crate-type = ["cdylib"]
[dependencies.pyo3]
version = "0.4"
features = ["extension-module"]
src/lib.rs
#![feature(specialization)]
#[macro_use]
extern crate pyo3;
use pyo3::prelude::*;
#[pyfunction]
/// Formats the sum of two numbers as string
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
Ok((a + b).to_string())
}
/// This module is a python module implemented in Rust.
#[pymodinit]
fn string_sum(py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_function!(sum_as_string))?;
Ok(())
}
On windows and linux, you can build normally with cargo build --release
. On macOS, you need to set additional linker arguments. One option is to compile with cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup
, the other is to create a .cargo/config
with the following content:
[target.x86_64-apple-darwin]
rustflags = [
"-C", "link-arg=-undefined",
"-C", "link-arg=dynamic_lookup",
]
For developing, you can copy and rename the shared library from the target folder: On macOS, rename libstring_sum.dylib
to string_sum.so
, on windows libstring_sum.dll
to string_sum.pyd
and on linux libstring_sum.so
to libstring_sum.so
. Then open a python shell in the same folder and you'll be able to import string_sum
.
To build, test and publish your crate as python module, you can use pyo3-pack or setuptools-rust. You can find an example for setuptools-rust in examples/word-count, while pyo3-pack should work on your crate without any configuration.
Add pyo3
this to your Cargo.toml
:
[dependencies]
pyo3 = "0.4"
Example program displaying the value of sys.version
:
#![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::types::PyDict;
fn main() -> PyResult<()> {
let gil = Python::acquire_gil();
let py = gil.python();
let sys = py.import("sys")?;
let version: String = sys.get("version")?.extract()?;
let locals = PyDict::new(py);
locals.set_item("os", py.import("os")?)?;
let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract()?;
println!("Hello {}, I'm Python {}", user, version);
Ok(())
}
- examples/word-count Counting the occurrences of a word in a text file
- hyperjson A hyper-fast Python module for reading/writing JSON data using Rust's serde-json
- rust-numpy Rust binding of NumPy C-API
- html-py-ever Using html5ever through kuchiki to speed up html parsing and css-selecting.
- pyo3-built Simple macro to expose metadata obtained with the
built
crate as aPyDict
- point-process High level API for pointprocesses as a Python library
- autopy A simple, cross-platform GUI automation library for Python and Rust.
PyO3 is licensed under the Apache-2.0 license. Python is licensed under the Python License.