Python 的 Rust 绑定,包括用于创建本机 Python 扩展模块的工具。还支持从 Rust 二进制文件运行 Python 代码并与之交互。
用户指南:稳定|主要的
API 文档:稳定 |主要的
需要 Rust 1.63 或更高版本。
PyO3 支持以下 Python 发行版:
您可以使用 PyO3 在 Rust 中编写本机 Python 模块,或将 Python 嵌入 Rust 二进制文件中。以下部分依次解释其中的每一个。
PyO3 可用于生成本机 Python 模块。第一次尝试的最简单方法是使用maturin
。 maturin
是一个用最少的配置构建和发布基于 Rust 的 Python 包的工具。以下步骤安装maturin
,使用它生成和构建新的 Python 包,然后启动 Python 以导入并执行包中的函数。
首先,按照以下命令创建一个包含新 Python virtualenv
新目录,并使用 Python 的包管理器pip
将maturin
安装到 virtualenv 中:
# (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
仍在该string_sum
目录中,现在运行maturin init
。这将生成新的包源。当选择要使用的绑定时,选择 pyo3 绑定:
$ maturin init
✔ ? What kind of bindings to use ? · pyo3
Done ! New project created string_sum
此命令生成的最重要的文件是Cargo.toml
和lib.rs
,它们大致如下所示:
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 ( ( ) )
}
最后,运行maturin develop
。这将构建包并将其安装到之前创建和激活的 Python virtualenv 中。然后就可以从python
使用该包了:
$ maturin develop
# lots of progress output as maturin runs the compilation...
$ python
>>> import string_sum
>>> string_sum.sum_as_string(5, 20)
' 25 '
要对包进行更改,只需编辑 Rust 源代码,然后重新运行maturin develop
即可重新编译。
要将这一切作为单个复制和粘贴来运行,请使用下面的 bash 脚本(将第一个命令中的string_sum
替换为所需的包名称):
mkdir string_sum && cd " $_ "
python -m venv .env
source .env/bin/activate
pip install maturin
maturin init --bindings pyo3
maturin develop
如果您希望能够运行cargo test
或在货物工作区中使用此项目并且遇到链接器问题,常见问题解答中提供了一些解决方法。
与maturin
一样,可以使用setuptools-rust
或手动进行构建。两者都比maturin
提供了更多的灵活性,但需要更多的配置才能开始。
要将 Python 嵌入 Rust 二进制文件,您需要确保您的 Python 安装包含共享库。以下步骤演示了如何确保这一点(对于 Ubuntu),然后给出一些运行嵌入式 Python 解释器的示例代码。
要在 Ubuntu 上安装 Python 共享库:
sudo apt install python3-dev
要在基于 RPM 的发行版(例如 Fedora、Red Hat、SuSE)上安装 Python 共享库,请安装python3-devel
软件包。
使用cargo new
启动一个新项目,并将pyo3
添加到Cargo.toml
中,如下所示:
[ dependencies . pyo3 ]
version = " 0.23.3 "
features = [ " auto-initialize " ]
显示sys.version
值和当前用户名的示例程序:
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 ( ( ) )
} )
}
该指南有一个部分包含许多有关该主题的示例。
built
板条箱获得的元数据公开为PyDict
欢迎大家为 PyO3 做出贡献!支持该项目的方式有很多,例如:
如果您愿意为 PyO3 贡献时间并正在寻找从哪里开始,我们的贡献笔记和架构指南有更多资源。
如果您没有时间做出贡献,但仍希望支持项目未来的成功,我们的一些维护人员有 GitHub 赞助页面:
PyO3 根据 Apache-2.0 许可证或 MIT 许可证获得许可,具体由您选择。
Python 根据 Python 许可证获得许可。
除非您另有明确说明,否则您有意提交的包含在 PyO3 中的任何贡献(如 Apache 许可证中所定义)应如上所述获得双重许可,没有任何附加条款或条件。