#cargo-toml #python-packages #python-bindings #pyo3 #c-ffi #python #packaging

bin+lib maturin

使用pyo3、cffi和uniffi绑定以及Rust二进制文件作为Python包构建和发布crates

230个版本 (16个稳定版)

1.7.1 2024年8月21日
1.7.0 2024年7月7日
1.6.0 2024年6月4日
1.5.1 2024年3月21日
0.7.7 2019年11月15日

12 in FFI

Download history 856/week @ 2024-05-01 935/week @ 2024-05-08 915/week @ 2024-05-15 546/week @ 2024-05-22 461/week @ 2024-05-29 568/week @ 2024-06-05 486/week @ 2024-06-12 430/week @ 2024-06-19 428/week @ 2024-06-26 732/week @ 2024-07-03 452/week @ 2024-07-10 423/week @ 2024-07-17 638/week @ 2024-07-24 440/week @ 2024-07-31 358/week @ 2024-08-07 298/week @ 2024-08-14

1,811 每月下载量
用于 direct-neural-biasing

MIT/Apache

600KB
13K SLoC

Maturin

之前为pyo3-pack

Maturin User Guide Crates.io PyPI Actions Status FreeBSD discord server

使用pyo3、cffi和uniffi绑定以及Rust二进制文件作为Python包构建和发布crates,配置最小化。它支持在Windows、Linux、mac和FreeBSD上构建Python 3.8+的wheels,可以上传到pypi,并提供基本的pypy和graalpy支持。

查看用户指南

使用方法

您可以从最新版本下载二进制文件,或者使用pipx安装。

pipx install maturin

[!NOTE]

pip install maturin如果您不使用pipx也应该可以工作。

有四个主要命令

  • maturin new创建一个新的带有maturin配置的Cargo项目。
  • maturin publish将crate构建为Python包并发布到pypi。
  • maturin build构建wheels并将它们存储在文件夹中(默认为target/wheels),但不上传。可以使用twinematurin upload上传这些。
  • maturin develop构建crate并将其作为Python模块直接安装到当前虚拟环境中。请注意,虽然maturin develop更快,但它不支持maturin build之后运行pip install支持的所有功能。

pyo3 绑定会自动检测。对于 cffi 或二进制文件,您需要传递 -b cffi-b bin。maturin 不需要额外的配置文件,也不会与现有的 setuptools-rust 或 milksnake 配置冲突。您甚至可以将其与测试工具(如 tox)集成。不同绑定的示例可以在 test-crates 文件夹中找到。

包的名称将是 cargo 项目的名称,即 Cargo.toml 中的 [package] 部分的名称字段。您导入时使用的模块名称将是 [lib] 部分的 name 值(默认为包的名称)。对于二进制文件,它简单地是 cargo 生成的二进制文件的名称。

Python 打包基础知识

Python 包有两种格式:一种称为 wheel 的构建形式和源代码分发(sdist),两者都是归档。wheel 可以与任何 Python 版本、解释器(主要是 cpython 和 pypy)以及操作系统和硬件架构兼容(对于纯 Python wheel),可以限制为特定平台和架构(例如,当使用 ctypes 或 cffi 时)或限制为特定架构和操作系统上的特定 Python 解释器和版本(例如,使用 pyo3)。

当使用 pip install 在包上时,pip 会尝试找到匹配的 wheel 并安装它。如果找不到,它会下载源代码分发并构建当前平台的 wheel,这需要安装正确的编译器。安装 wheel 的速度比安装源代码分发快得多,因为构建 wheel 通常很慢。

当您使用 pip install 发布可安装的包时,您将其上传到官方包仓库 pypi。对于测试,您可以使用 test pypi,您可以使用 pip install --index-url https://test.pypi.org/simple/。请注意,对于 Linux 的发布,您需要使用 manylinux docker 容器,而对于从您的仓库发布,您可以使用 PyO3/maturin-action github action

pyo3

对于 pyo3,maturin 只能为已安装的 Python 版本构建包。在 Linux 和 macOS 上,使用 PATH 中的所有 Python 版本。如果您没有使用 -i 设置自己的解释器,则会使用启发式方法搜索 Python 安装。在 Windows 上,使用 Python 捕获器(默认由 python.org 安装程序安装)中的所有版本以及除 base 之外的所有 conda 环境。您可以使用 list-python 子命令检查哪些版本被选中。

pyo3 将在环境变量 PYTHON_SYS_EXECUTABLE 中设置使用的 Python 解释器,这可以从自定义构建脚本中使用。尽管只在 Linux 上对 pypy3.7-7.3 进行了测试,但 maturin 可以使用 pyo3 构建和上传 pypy 的 wheel。

Cffi

Cffi wheel 与所有 Python 版本兼容,包括 pypy。如果未安装 cffi 且 Python 在虚拟环境中运行,maturin 会安装它,否则您必须自己安装它(pip install cffi)。

maturin 使用 cbindgen 生成头文件,可以通过在项目根目录内配置 cbindgen.toml 文件来自定义 cbindgen。或者,你可以使用构建脚本来将头文件写入 $PROJECT_ROOT/target/header.h

基于生成的头文件,maturin 会创建一个模块,该模块导出 ffilib 对象。

自定义构建脚本示例
use cbindgen;
use std::env;
use std::path::Path;

fn main() {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

    let bindings = cbindgen::Builder::new()
        .with_no_includes()
        .with_language(cbindgen::Language::C)
        .with_crate(crate_dir)
        .generate()
        .unwrap();
    bindings.write_to_file(Path::new("target").join("header.h"));
}

uniffi

uniffi 绑定使用 uniffi-rs 从接口定义文件生成 Python ctypes 绑定。uniffi 轮适用于所有 Python 版本,包括 pypy。

混合 Rust/Python 项目

要创建混合 Rust/Python 项目,在 Cargo.toml 旁边创建一个以你的模块名称命名的文件夹(例如 lib.name),并将你的 Python 代码放在那里。

my-project
├── Cargo.toml
├── my_project
│   ├── __init__.py
│   └── bar.py
├── pyproject.toml
├── README.md
└── src
    └── lib.rs

你可以在 pyproject.toml 中指定不同的 Python 源目录,通过设置 tool.maturin.python-source,例如:

pyproject.toml

[tool.maturin]
python-source = "python"
module-name = "my_project._lib_name"

然后,项目结构将如下所示:

my-project
├── Cargo.toml
├── python
│   └── my_project
│       ├── __init__.py
│       └── bar.py
├── pyproject.toml
├── README.md
└── src
    └── lib.rs

[!NOTE]

推荐使用这种结构以避免 常见的 ImportError 陷阱

maturin 将将原生扩展作为模块添加到你的 Python 目录。当使用 develop 时,maturin 将复制原生库和 cffi 的粘合代码到你的 Python 目录。你应该将这些文件添加到 gitignore 中。

使用 cffi,你可以这样做 from .my_project import lib 然后使用 lib.my_native_function,使用 pyo3,你可以直接 from .my_project import my_native_function

使用 pyo3 在 maturin develop 后的布局示例

my-project
├── Cargo.toml
├── my_project
│   ├── __init__.py
│   ├── bar.py
│   └── _lib_name.cpython-36m-x86_64-linux-gnu.so
├── README.md
└── src
    └── lib.rs

在这样做的时候,也请确保将代码中的模块名称设置为与 module-name 的最后一部分匹配(不要包含包路径)

#[pymodule]
#[pyo3(name="_lib_name")]
fn my_lib_name(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
    m.add_class::<MyPythonRustClass>()?;
    Ok(())
}

Python 元数据

maturin 支持 PEP 621,你可以在 pyproject.toml 中指定 Python 包元数据。maturin 会合并来自 Cargo.tomlpyproject.toml 的元数据,pyproject.toml 优先于 Cargo.toml

要指定 Python 依赖项,在 pyproject.toml 中的 [project] 节中添加一个 dependencies 列表。此列表与 setuptools 中的 install_requires 相当。

[project]
name = "my-project"
dependencies = ["flask~=1.1.0", "toml==0.10.0"]

Pip 允许添加所谓的控制台脚本,它们是执行程序中某些功能的 shell 命令。你可以在 [project.scripts] 节中添加控制台脚本。键是脚本名称,值是以 some.module.path:class.function 格式表示的函数路径,其中 class 部分是可选的。函数不带参数调用。示例:

[project.scripts]
get_42 = "my_project:DummyClass.get_42"

你还可以在 pyproject.toml 中的 project.classifiers 下指定 Trove 类别

[project]
name = "my-project"
classifiers = ["Programming Language :: Python"]

源分发

maturin 支持通过 pyproject.toml 构建。要使用它,请在您的 Cargo.toml 旁边创建一个 pyproject.toml,内容如下:

[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"

如果存在一个包含 [build-system] 条目的 pyproject.toml,当指定 --sdist 时,maturin 可以构建您包的源分发版。源分发版将包含与 cargo package 相同的文件。要仅构建源分发版,传递 --interpreter 而不提供任何值。

然后,例如,您可以使用 pip install . 安装您的包。使用 pip install . -v 您可以看到 cargo 和 maturin 的输出。

您可以在 [tool.maturin] 下使用选项 compatibilityskip-auditwheelbindingsstrip 和常见的 Cargo 构建选项,例如 features,与直接运行 maturin 时相同。对于 cffi 和 bin 项目,需要 bindings 键,因为这些无法自动检测。目前,所有构建都在发布模式下进行(有关详细信息,请参阅 此线程)。

对于具有 cffi 绑定的非 manylinux 构建,您可以使用以下内容

[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"

[tool.maturin]
bindings = "cffi"
compatibility = "linux"

manylinux 选项也接受为 compatibility 的别名,以便与旧版本的 maturin 兼容。

要包括任意文件在 sdist 中用于编译,请指定 includepath 路径通配符数组,并将 format 设置为 sdist

[tool.maturin]
include = [{ path = "path/**/*", format = "sdist" }]

有一个 maturin sdist 命令,仅用于构建源分发版,作为 pypa/pip#6041 的解决方案。

Manylinux 和 auditwheel

出于可移植性的原因,Linux 上的本地 Python 模块必须仅动态链接一组非常少的库,这些库基本上到处都安装了,因此得名 manylinux。pypa 提供特殊的 docker 镜像和名为 auditwheel 的工具,以确保符合 manylinux 规则。如果您想要发布广泛使用的 Linux PyPI 轮子,您需要使用 manylinux docker 镜像

从版本 1.64 开始,Rust 编译器 需要至少 glibc 2.17,因此您需要使用至少 manylinux2014。对于发布,我们建议使用与镜像相同的 manylinux 版本,例如,如果您在 quay.io/pypa/manylinux2014_x86_64 上构建,则使用 --manylinux 2014。如果设置了 manylinux: 2014,则 PyO3/maturin-action github 动作已经处理了这一点。

maturin 包含 auditwheel 的重实现,自动检查生成的库,并给 wheel 赋予正确的平台标签。如果您的系统 glibc 太新或链接其他共享库,它将分配 linux 标签。您也可以手动禁用这些检查,并直接使用本机 Linux 目标,使用 --manylinux off

为了完全符合 manylinux 标准,您需要在 CentOS Docker 容器中编译。基于 manylinux2014 图像的 pyo3/maturin 镜像会将参数传递给 maturin 可执行文件。您可以使用如下方式

docker run --rm -v $(pwd):/io ghcr.io/pyo3/maturin build --release  # or other maturin arguments

请注意,此镜像非常基础,仅包含 python、maturin 和稳定的 Rust。如果您需要额外的工具,您可以在 manylinux 容器内运行命令。请参考 konstin/complex-manylinux-maturin-docker 以了解一个简单的教育示例或 nanoporetech/fast-ctc-decode 了解实际配置。

maturin 本身在针对 musl 目标编译时符合 manylinux 标准。

示例

  • ballista-python - 一个 Python 库,用于连接 Apache Arrow 分布式查询引擎 Ballista
  • bleuscore - 一个 BLEU 分数计算库,使用纯 Rust 编写
  • chardetng-py - chardetng 字符编码检测器的 Python 绑定
  • connector-x - ConnectorX 使您能够以最快和最节省内存的方式将数据从数据库加载到 Python
  • datafusion-python - 一个 Python 库,用于绑定 Apache Arrow 内存查询引擎 DataFusion
  • deltalake-python - 基于 delta-rs 的原生 Delta Lake Python 绑定,具有 Pandas 集成
  • opendal - OpenDAL Python 绑定,用于自由访问数据
  • orjson - 一个快速、正确的 Python JSON 库
  • polars - Rust、Python 和 Node.js 中快速的多线程 DataFrame 库
  • pydantic-core - pydantic 的核心验证逻辑,使用 Rust 编写
  • pyrus-cramjam - 对 Rust 中的解/压缩算法的精简 Python 包装器
  • pyxel - 一个用于 Python 的复古游戏引擎
  • roapi - ROAPI 可自动启动针对静态数据集的只读 API,无需您编写任何代码
  • robyn - 一个快速且可扩展的异步 Python 网络服务器,具有 Rust 运行时
  • ruff - 一个极快的 Python 代码检查器,使用 Rust 编写
  • tantivy-py - Tantivy 的 Python 绑定
  • watchfiles - 简单、现代且高性能的 Python 文件监控和代码重新加载
  • wonnx - 由 Rust 完全编写的 GPU 加速 ONNX 推理运行时

贡献

欢迎每个人为 maturin 贡献!有许多方式可以支持项目,例如

  • 帮助 GitHub 和 Gitter 上的 maturin 用户解决 issues
  • 改进文档
  • 编写功能和错误修复
  • 发布关于如何使用 maturin 的博客和示例

我们的 贡献指南 提供了更多资源,如果您想为 maturin 贡献时间并寻找开始的地方。

如果您没有时间自行贡献,但仍然希望支持项目的未来发展,我们的一些维护者有 GitHub 赞助页面

许可证

根据以下其中之一授权

根据您的选择。

依赖项

~30–49MB
~1M SLoC