PyO3/maturin
GitHub: PyO3/maturin
一款简化 Rust 到 Python 扩展构建与发布流程的工具,支持多种绑定方式和跨平台 wheel 打包。
Stars: 5434 | Forks: 383
# Maturin
_原名 pyo3-Pack_
[](https://maturin.rs)
[](https://crates.io/crates/maturin)
[](https://pypi.org/project/maturin)
[](https://discord.gg/33kcChzH7f)
构建并发布带有 [pyo3, cffi 和 uniffi bindings](https://maturin.rs/bindings) 的 crate,以及作为 Python 包的 Rust 二进制文件,只需极简的配置。
它支持为 Windows、Linux、macOS 和 FreeBSD 上的 Python 3.8+ 构建 wheel,可以将它们上传到 [pypi](https://pypi.org/),并具有基本的 PyPy 和 GraalPy 支持。
查看 [用户指南](https://maturin.rs/)!
## 用法
你可以从 [最新版本](https://github.com/PyO3/maturin/releases/latest) 下载二进制文件,或者使用 [pipx](https://pypa.github.io/pipx/) 或 [uv](https://github.com/astral-sh/uv) 安装:
```
# pipx
pipx install maturin
# uv
uv tool install maturin
```
主要有三个命令:
- `maturin new` 创建一个配置了 maturin 的新 cargo 项目。
- `maturin build` 构建 wheel 并将其存储在一个文件夹中(默认为 `target/wheels`),但不会上传它们。建议使用 [uv](https://github.com/astral-sh/uv) 通过 `uv publish` 来发布包。
- `maturin develop` 构建 crate 并将其作为 python 模块直接安装在当前的 virtualenv 中。请注意,虽然 `maturin develop` 更快,但它不支持 `maturin build` 后运行 `pip install` 所支持的所有功能。
maturin 不需要额外的配置文件,也不会与现有的 setuptools-rust 配置冲突。
你甚至可以将其与 [tox](https://tox.readthedocs.io/en/latest/) 等测试工具集成。
`test-crates` 文件夹中有不同 bindings 的示例。
包的名称将是 cargo 项目的名称,即 `Cargo.toml` 中 `[package]` 部分的 name 字段。
你导入时使用的模块名称,将是 `[lib]` 部分中的 `name` 值(默认为包的名称)。对于二进制文件,它只是 cargo 生成的二进制文件的名称。
使用 `maturin build` 和 `maturin develop` 命令时,可以通过添加 `-r` 或 `--release` 标志来编译性能优化的程序。
## Python 打包基础知识
Python 包有两种格式:
一种称为 wheel 的构建形式和源代码分发 (sdist),两者都是归档文件。
wheel 可以兼容任何 python 版本、解释器(主要是 cpython 和 pypy)、操作系统和硬件架构(对于纯 python wheel),
可以限于特定的平台和架构(例如使用 ctypes 或 cffi 时),或者限于特定架构和操作系统上的特定 python 解释器和版本(例如使用 pyo3 时)。
当对包使用 `pip install` 时,pip 会尝试找到匹配的 wheel 并安装它。如果没有找到,它会下载源代码分发并为当前平台构建 wheel,
这需要安装正确的编译器。安装 wheel 比安装源代码分发要快得多,因为构建 wheel 通常很慢。
当你发布一个可以通过 `pip install` 安装的包时,你需要将其上传到 [pypi](https://pypi.org/),即官方包仓库。
为了测试,你可以改用 [test pypi](https://test.pypi.org/),可以通过 `pip install --index-url https://test.pypi.org/simple/` 来使用它。
请注意,对于[为 linux 发布](#manylinux-and-auditwheel),你需要使用 manylinux docker 容器或 zig,而从你的仓库发布时,你可以使用 [PyO3/maturin-action](https://github.com/PyO3/maturin-action) github action。
## 混合 Rust/Python 项目
要创建一个混合 rust/python 项目,请在你的 Cargo.toml 旁边创建一个以你的模块名称(即 Cargo.toml 中的 `lib.name`)命名的文件夹,并在那里添加你的 python 源代码:
```
my-project
├── Cargo.toml
├── my_project
│ ├── __init__.py
│ └── bar.py
├── pyproject.toml
├── README.md
└── src
└── lib.rs
```
你可以在 `pyproject.toml` 中通过设置 `tool.maturin.python-source` 来指定不同的 python 源目录,例如
**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
```
maturin 会将原生扩展作为模块添加到你的 python 文件夹中。使用 develop 时,maturin 会将原生库复制到你的 python 文件夹,对于 cffi 还会复制胶水代码。你应该将这些文件添加到你的 gitignore 中。
使用 cffi,你可以执行 `from .my_project import lib` 然后使用 `lib.my_native_function`,使用 pyo3 你可以直接 `from .my_project import my_native_function`。
`maturin develop` 之后的 pyo3 示例布局:
```
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(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::()?;
Ok(())
}
```
## Python 元数据
maturin 支持 [PEP 621](https://www.python.org/dev/peps/pep-0621/),你可以在 `pyproject.toml` 中指定 python 包元数据。
maturin 合并来自 `Cargo.toml` 和 `pyproject.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.2,<0.11.0"]
```
你可以添加所谓的控制台脚本,它们是在 `[project.scripts]` 部分执行程序中某些功能的 shell 命令。
键是脚本名称,而值是函数的路径,格式为 `some.module.path:class.function`,其中 `class` 部分是可选的。该函数在无参数情况下被调用。示例:
```
[project.scripts]
get_42 = "my_project:DummyClass.get_42"
```
你也可以在 `pyproject.toml` 的 `project.classifiers` 下指定 [trove classifiers](https://pypi.org/classifiers/):
```
[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]` 下使用选项 `compatibility`、`skip-auditwheel`、`bindings`、`strip` 和常见的 Cargo 构建选项(如 `features`),方式与直接运行 maturin 时相同。
`bindings` 键对于 cffi 和 bin 项目是必需的,因为这些无法自动检测。目前,所有构建都在发布模式下进行(有关详细信息,请参阅[此主题](https://discuss.python.org/t/pep-517-debug-vs-release-builds/1924))。
对于带有 cffi bindings 的非 manylinux 构建,你可以使用以下内容:
```
[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"
[tool.maturin]
bindings = "cffi"
compatibility = "linux"
```
为了向后兼容旧版本的 maturin,也接受 `manylinux` 选项作为 `compatibility` 的别名。
要在编译期间将任意文件包含在 sdist 中,请将 `include` 指定为 `path` glob 数组,并将 `format` 设置为 `sdist`:
```
[tool.maturin]
include = [{ path = "path/**/*", format = "sdist" }]
```
有一个 `maturin sdist` 命令仅用于构建源代码分发,作为 [pypa/pip#6041](https://github.com/pypa/pip/issues/6041) 的变通方法。
## Manylinux 和 auditwheel
出于可移植性原因,Linux 上的原生 python 模块必须仅动态链接极少数基本到处都安装的库集,因此得名 manylinux。
pypa 提供特殊的 docker 镜像和一个名为 [auditwheel](https://github.com/pypa/auditwheel/) 的工具来确保符合 [manylinux 规则](https://peps.python.org/pep-0599/#the-manylinux2014-policy)。
如果你想为 linux pypi 发布广泛可用的 wheel,**你需要使用 manylinux docker 镜像或使用 zig 构建**。
自 1.64 版本起,Rust 编译器[至少需要 glibc 2.17](https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html),因此你需要至少使用 manylinux2014。
对于发布,我们建议使用 manylinux 标志强制执行与镜像相同的 manylinux 版本,例如,如果你在 `quay.io/pypa/manylinux2014_x86_64` 中构建,请使用 `--manylinux 2014`。
如果你设置例如 `manylinux: 2014`,[PyO3/maturin-action](https://github.com/PyO3/maturin-action) github action 已经处理了这个问题。
maturin 包含 auditwheel 的重新实现,会自动检查生成的库并为 wheel 提供适当的平台标签。
如果你系统的 glibc 太新或者你链接了其他共享库,它将分配 `linux` 标签。
你也可以手动禁用这些检查,并使用 `--manylinux off` 直接使用原生 linux 目标。
为了完全符合 manylinux,你需要在 CentOS docker 容器中编译。[pyo3/maturin](https://ghcr.io/pyo3/maturin) 镜像基于 manylinux2014 镜像,
并将参数传递给 `maturin` 二进制文件。你可以像这样使用它:
```
docker run --rm -v $(pwd):/io ghcr.io/pyo3/maturin build --release # or other maturin arguments
```
请注意,此镜像非常基础,仅包含 python、maturin 和 stable rust。如果你需要额外的工具,可以在 manylinux 容器内运行命令。
有关小型教育示例,请参阅 [konstin/complex-manylinux-maturin-docker](https://github.com/konstin/complex-manylinux-maturin-docker);有关真实世界的设置,请参阅 [nanoporetech/fast-ctc-decode](https://github.com/nanoporetech/fast-ctc-decode/blob/b226ea0f2b2f4f474eff47349703d57d2ea4801b/.github/workflows/publish.yml)。
当为 musl 目标编译时,maturin 本身是符合 manylinux 的。
## 示例
- [agg-python-bindings](https://pypi.org/project/agg-python-bindings) - 一个绑定到 Asciinema Agg 终端记录渲染器和 Avt 终端模拟器的 Python 库
- [ballista-python](https://github.com/apache/arrow-ballista-python) - 一个绑定到 Apache Arrow 分布式查询引擎 Ballista 的 Python 库
- [bleuscore](https://github.com/shenxiangzhuang/bleuscore) - 一个 BLEU 分数计算库,用纯 Rust 编写
- [chardetng-py](https://github.com/john-parton/chardetng-py) - chardetng 字符编码检测器的 Python 绑定。
- [connector-x](https://github.com/sfu-db/connector-x/tree/main/connectorx-python) - ConnectorX 使你能够以最快和最节省内存的方式将数据从数据库加载到 Python
- [datafusion-python](https://github.com/apache/arrow-datafusion-python) - 一个绑定到 Apache Arrow 内存查询引擎 DataFusion 的 Python 库
- [deltalake-python](https://github.com/delta-io/delta-rs/tree/main/python) - 基于 delta-rs 的原生 Delta Lake Python 绑定,带有 Pandas 集成
- [opendal](https://github.com/apache/incubator-opendal/tree/main/bindings/python) - 自由访问数据的 OpenDAL Python 绑定
- [orjson](https://github.com/ijl/orjson) - 一个快速、正确的 Python JSON 库
- [polars](https://github.com/pola-rs/polars/tree/master/py-polars) - Rust | Python | Node.js 中快速的多线程 DataFrame 库
- [pydantic-core](https://github.com/pydantic/pydantic-core) - 用 Rust 编写的 pydantic 核心验证逻辑
- [pyrus-cramjam](https://github.com/milesgranger/pyrus-cramjam) - 用于 Rust 中解/压缩算法的轻量级 Python 封装
- [pyxel](https://github.com/kitao/pyxel) - 一个 Python 复古游戏引擎
- [roapi](https://github.com/roapi/roapi) - ROAPI 自动为静态数据集启动只读 API,无需你编写一行代码
- [robyn](https://github.com/sansyrox/robyn) - 具有 Rust 运行时的快速且可扩展的异步 python web 服务器
- [ruff](https://github.com/charliermarsh/ruff) - 一个极快的 Python linter,用 Rust 编写
- [rnet](https://github.com/0x676e67/rnet) - 具有 Black Magic 的异步 Python HTTP 客户端
- [rustpy-xlsxwriter](https://github.com/rahmadafandi/rustpy-xlsxwriter): 一个用于生成 Excel 文件的高性能 Python 库,利用 [rust_xlsxwriter](https://github.com/jmcnamara/rust_xlsxwriter) crate 进行高效数据处理。
- [tantivy-py](https://github.com/quickwit-oss/tantivy-py) - Tantivy 的 Python 绑定
- [tpchgen-cli](https://github.com/clflushopt/tpchgen-rs/tree/main/tpchgen-cli) - `tpchgen` 的 Python CLI 绑定,这是一个用纯 Rust 构建且零依赖的极快 TPC-H 基准数据生成器。
- [watchfiles](https://github.com/samuelcolvin/watchfiles) - python 中简单、现代和高性能的文件监视和代码重载
- [wonnx](https://github.com/webonnx/wonnx/tree/master/wonnx-py) - Wonnx 是一个用 100% Rust 编写的 GPU 加速 ONNX 推理运行时
## 许可证
根据以下之一许可:
- Apache License, Version 2.0, ([LICENSE-APACHE](https://github.com/PyO3/maturin/blob/main/license-apache) 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](https://github.com/PyO3/maturin/blob/main/license-mit) 或 http://opensource.org/licenses/MIT)
你选择。
标签:cffi, CLI, FFI, PyO3, PyPI, Python, Rust, SOC Prime, UniFFI, WiFi技术, 二进制, 可视化界面, 库, 应急响应, 开发工具, 性能优化, 打包工具, 无后门, 构建系统, 检测绕过, 混合编程, 绑定, 网络流量审计, 网络调试, 自动化, 请求拦截, 轮子, 逆向工具, 通知系统, 通知系统