Enlaces de Rust para Python, incluidas herramientas para crear módulos de extensión nativos de Python. También se admite la ejecución e interacción con código Python desde un binario de Rust.
Guía del usuario: estable | principal
Documentación API: estable | principal
Requiere Rust 1.63 o superior.
PyO3 admite las siguientes distribuciones de Python:
Puede usar PyO3 para escribir un módulo nativo de Python en Rust o para incrustar Python en un binario de Rust. Las siguientes secciones explican cada uno de estos por separado.
PyO3 se puede utilizar para generar un módulo nativo de Python. La forma más sencilla de probar esto por primera vez es utilizar maturin
. maturin
es una herramienta para crear y publicar paquetes Python basados en Rust con una configuración mínima. Los siguientes pasos instalan maturin
, lo utilizan para generar y construir un nuevo paquete de Python y luego inician Python para importar y ejecutar una función del paquete.
Primero, siga los siguientes comandos para crear un nuevo directorio que contenga un nuevo virtualenv
de Python e instale maturin
en el virtualenv usando el administrador de paquetes de Python, pip
:
# (replace string_sum with the desired package name)
$ mkdir string_sum
$ cd string_sum
$ python -m venv .env
$ source .env/bin/activate
$ pip install maturin
Aún dentro de este directorio string_sum
, ahora ejecute maturin init
. Esto generará la nueva fuente del paquete. Cuando se le dé la opción de usar enlaces, seleccione enlaces pyo3:
$ maturin init
✔ ? What kind of bindings to use ? · pyo3
Done ! New project created string_sum
Los archivos más importantes generados por este comando son Cargo.toml
y lib.rs
, que tendrán un aspecto similar al siguiente:
Cargo.toml
[ package ]
name = " string_sum "
version = " 0.1.0 "
edition = " 2021 "
[ lib ]
# The name of the native library. This is the name which will be used in Python to import the
# library (i.e. `import string_sum`). If you change this, you must also change the name of the
# `#[pymodule]` in `src/lib.rs`.
name = " string_sum "
# "cdylib" is necessary to produce a shared library for Python to import from.
#
# Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able
# to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.:
# crate-type = ["cdylib", "rlib"]
crate-type = [ " cdylib " ]
[ dependencies ]
pyo3 = { version = " 0.23.3 " , features = [ " extension-module " ] }
src/lib.rs
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. The name of this function must match
/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to
/// import the module.
# [ pymodule ]
fn string_sum ( m : & Bound < ' _ , PyModule > ) -> PyResult < ( ) > {
m . add_function ( wrap_pyfunction ! ( sum_as_string , m ) ? ) ? ;
Ok ( ( ) )
}
Finalmente, maturin develop
. Esto creará el paquete y lo instalará en el virtualenv de Python creado y activado previamente. El paquete estará entonces listo para ser utilizado desde python
:
$ maturin develop
# lots of progress output as maturin runs the compilation...
$ python
>>> import string_sum
>>> string_sum.sum_as_string(5, 20)
' 25 '
Para realizar cambios en el paquete, simplemente edite el código fuente de Rust y luego vuelva a ejecutar maturin develop
para volver a compilarlo.
Para ejecutar todo esto como un solo copiar y pegar, use el siguiente script bash (reemplace string_sum
en el primer comando con el nombre del paquete deseado):
mkdir string_sum && cd " $_ "
python -m venv .env
source .env/bin/activate
pip install maturin
maturin init --bindings pyo3
maturin develop
Si desea poder ejecutar cargo test
o utilizar este proyecto en un espacio de trabajo de Cargo y tiene problemas con el vinculador, existen algunas soluciones en las preguntas frecuentes.
Además de con maturin
, es posible compilar utilizando setuptools-rust
o manualmente. Ambos ofrecen más flexibilidad que maturin
pero requieren más configuración para comenzar.
Para incrustar Python en un binario de Rust, debe asegurarse de que su instalación de Python contenga una biblioteca compartida. Los siguientes pasos demuestran cómo garantizar esto (para Ubuntu) y luego brindan un código de ejemplo que ejecuta un intérprete de Python integrado.
Para instalar la biblioteca compartida de Python en Ubuntu:
sudo apt install python3-dev
Para instalar la biblioteca compartida de Python en distribuciones basadas en RPM (por ejemplo, Fedora, Red Hat, SuSE), instale el paquete python3-devel
.
Inicie un nuevo proyecto con cargo new
y agregue pyo3
a Cargo.toml
de esta manera:
[ dependencies . pyo3 ]
version = " 0.23.3 "
features = [ " auto-initialize " ]
Programa de ejemplo que muestra el valor de sys.version
y el nombre de usuario actual:
use pyo3 :: prelude :: * ;
use pyo3 :: types :: IntoPyDict ;
use pyo3 :: ffi :: c_str ;
fn main ( ) -> PyResult < ( ) > {
Python :: with_gil ( |py| {
let sys = py . import ( "sys" ) ? ;
let version : String = sys . getattr ( "version" ) ? . extract ( ) ? ;
let locals = [ ( "os" , py . import ( "os" ) ? ) ] . into_py_dict ( py ) ? ;
let code = c_str ! ( "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'" ) ;
let user : String = py . eval ( code , None , Some ( & locals ) ) ? . extract ( ) ? ;
println ! ( "Hello {}, I'm Python {}" , user , version ) ;
Ok ( ( ) )
} )
}
La guía tiene una sección con muchos ejemplos sobre este tema.
built
como un PyDict
¡Todos son bienvenidos a contribuir a PyO3! Hay muchas formas de apoyar el proyecto, tales como:
Nuestras notas de contribución y nuestra guía de arquitectura tienen más recursos si desea ofrecer tiempo como voluntario para PyO3 y está buscando por dónde empezar.
Si no tiene tiempo para contribuir pero aún desea apoyar el éxito futuro del proyecto, algunos de nuestros mantenedores tienen páginas de patrocinio de GitHub:
PyO3 tiene la licencia Apache-2.0 o la licencia MIT, a su elección.
Python tiene la licencia Python.
A menos que indique explícitamente lo contrario, cualquier contribución enviada intencionalmente por usted para su inclusión en PyO3, tal como se define en la Licencia Apache, tendrá una licencia doble como se indicó anteriormente, sin términos ni condiciones adicionales.