使用pyo3、cffi和uniffi绑定构建和发布crate以及作为Python包的二进制Rust程序
项目描述
matu-rin
以前称为pyo3-pack
使用pyo3、cffi和uniffi绑定以及rust二进制文件,将crate构建和发布为Python包,配置简单。它支持在Windows、Linux、mac和FreeBSD上构建Python 3.8+的wheel包,可以上传到PyPI,并具备基本的pypy和graalpy支持。
查看用户指南!
使用方法
您可以从最新版本发布中下载二进制文件,或者使用pipx进行安装。
pipx install maturin
[!注意]
如果不使用pipx,则也可以使用
pip install maturin
。
有四个主要命令
maturin new
创建一个新的带有maturin配置的Cargo项目。maturin publish
将crate构建成Python包并发布到PyPI。maturin build
构建wheel包并将其存储在文件夹中(默认为target/wheels
),但不会上传。可以使用twine或maturin 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生成的二进制文件名称。
在执行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,这是官方的包仓库。对于测试,可以使用测试PyPI,您可以使用pip install --index-url https://test.pypi.org/simple/
来使用它。请注意,对于Linux发布,您需要使用manylinux docker容器,而对于从您的仓库发布,您可以使用PyO3/maturin-action github动作。
pyo3
对于pyo3,maturin只能为已安装的Python版本构建软件包。在Linux和mac上,将使用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构建和上传wheels。
Cffi
Cffi wheels与所有Python版本兼容,包括pypy。如果cffi
未安装且Python在virtualenv内部运行,maturin将安装它;否则,您必须自己安装它(pip install cffi
)。
maturin使用cbindgen生成一个头文件,可以通过在项目根目录中配置cbindgen.toml
文件来自定义cbindgen。或者,您可以使用一个构建脚本,将头文件写入到$PROJECT_ROOT/target/header.h
。
基于头文件,maturin生成一个模块,它导出一个ffi
和一个lib
对象。
自定义构建脚本示例
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 wheels与所有Python版本兼容,包括pypy。
混合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
[!注意]
建议使用此结构以避免常见的
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
。
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(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<MyPythonRustClass>()?;
Ok(())
}
Python元数据
maturin支持PEP 621,您可以在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.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 的输出。
您可以使用 compatibility
、skip-auditwheel
、bindings
、strip
以及在 [tool.maturin]
下的常见 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 中,请指定 include
为一个包含 path
globs 的数组,并将 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 镜像。
Rust 编译器从版本 1.64 开始 需要至少 glibc 2.17,因此您需要使用至少 manylinux2014。对于发布,我们建议使用与具有 manylinux 标志的镜像相同的 manylinux 版本,例如,如果您在 quay.io/pypa/manylinux2014_x86_64
上构建,请使用 --manylinux 2014
。如果设置例如 manylinux: 2014
,PyO3/maturin-action github 动作已自动处理此问题。
maturin 包含 auditwheel 的重实现,自动检查生成的库,并为轮子分配正确的平台标签。如果您的系统 glibc 过新或链接其他共享库,它将分配 linux
标签。您还可以手动禁用这些检查,并直接使用带有 --manylinux off
的原生 Linux 目标。
为了完全符合 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 - 一个绑定到 Apache Arrow 分布式查询引擎 Ballista 的 Python 库
- bleuscore - 一个纯 Rust 编写的 BLEU 分数计算库
- chardetng-py - chardetng字符编码检测器的Python绑定。
- connector-x - ConnectorX使您能够以最快和最节省内存的方式将数据从数据库加载到Python中。
- datafusion-python - 一个Python库,它将Apache Arrow内存查询引擎DataFusion绑定。
- deltalake-python - 基于delta-rs且具有Pandas集成的原生Delta Lake Python绑定。
- 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 - 一个具有 Rust 运行时的快速且可扩展的异步 Python Web 服务器。
- ruff - 一个用 Rust 编写的极快 Python 检查器。
- tantivy-py - Tantivy 的 Python 绑定。
- watchfiles - 简单、现代且性能高效的 Python 文件监视和代码重载。
- wonnx - 100% 用 Rust 编写的 GPU 加速 ONNX 推理运行时。
贡献
每个人都欢迎为 maturin 贡献!有很多方式可以支持这个项目,例如
- 帮助 GitHub 和 Gitter 上的 maturin 用户处理问题
- 改进文档
- 编写功能和错误修复
- 发布有关如何使用 maturin 的博客和示例
我们的 贡献笔记 提供了更多资源,如果您想为 maturin 贡献时间并寻找起点。
如果您没有时间亲自贡献,但仍然希望支持项目的未来成功,我们的一些维护者有 GitHub 赞助页面
许可证
根据以下任一许可发布
- Apache License,版本 2.0,(LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证(LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任选其一。
项目详细信息
下载文件
下载适合您平台的文件。如果您不确定选择哪一个,请了解更多关于安装包的信息。
源代码分发
构建分发
maturin-1.7.4.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 2b349d742a07527d236f0b4b6cab26f53ebecad0ceabfc09ec4c6a396e3176f9 |
|
MD5 | f624546d5c253c62513e5c4f6380abfb |
|
BLAKE2b-256 | 512831a650d9209d873b6aec759c944bd284155154d7a01f7f541786d7c435ca |
maturin-1.7.4-py3-none-win_arm64.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | f3d38a6d0c7fd7b04bec30dd470b2173cf9bd184ab6220c1acaf49df6b48faf5 |
|
MD5 | 8c810c9cd541c3fc631154f56995bfa4 |
|
BLAKE2b-256 | 30388e27282ab6ff94291f04e3eb11ba960dfb487605d73cec75177d3a29879a |
maturin-1.7.4-py3-none-win_amd64.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | f70c1c8ec9bd4749a53c0f3ae8fdbb326ce45be4f1c5551985ee25a6d7150328 |
|
MD5 | 209785717b557e5ae13c84f7d330c2cd |
|
BLAKE2b-256 | 7250a9b402aa506bad6c066c7775b1cb3036b7b1c74b9de708ed537ee804ea4a |
maturin-1.7.4-py3-none-win32.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 35487a424467d1fda4567cbb02d21f09febb10eda22f5fd647b130bc0767dc61 |
|
MD5 | 56cd3e737f4e9ef33f45f939bbeae8af |
|
BLAKE2b-256 | a55d59765561ea1a5f993141a403eb4ae85b7a8bd118971de0ed14048e3faf7f |
maturin-1.7.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | fd5b4b95286f2f376437340f8a4908f4761587212170263084455be8099099a7 |
|
MD5 | 360f23beb6978d90c9b93c3e41fff424 |
|
BLAKE2b-256 | a4e915a24263de981928303ca64465d5d9d5062f248b9ceaab3de5857ee0ba83 |
哈希值 用于 maturin-1.7.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | c179fcb2b494f19186781b667320e43d95b3e71fcb1c98fffad9ef6bd6e276b3 |
|
MD5 | 0bda3d51ea1fcee335990d246f700391 |
|
BLAKE2b-256 | 7ffa8d9497c62451fc19f52cda1ad652c5dca4e9646ff93be35250070afbc2af |
哈希值 用于 maturin-1.7.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 71f668f19e719048605dbca6a1f4d0dc03b987c922ad9c4bf5be03b9b278e4c3 |
|
MD5 | e1825fc705b16159d5fb6977c9ceda34 |
|
BLAKE2b-256 | 53204b79324b14a1f39b2c66eb1ad681cf8b0fff1f905374b0cca59fc9c8ef7a |
哈希值 用于 maturin-1.7.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 7ccb66d0c5297cf06652c5f72cb398f447d3a332eccf5d1e73b3fe14dbc9498c |
|
MD5 | 616da9f976c5a12f7b50a93da689df40 |
|
BLAKE2b-256 | 3459e0d58ce67a8a6245dcb74ffb81cb12f0cda8b622c8d902f2371de742ae04 |
哈希值 用于 maturin-1.7.4-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 8b441521c151f0dbe70ed06fb1feb29b855d787bda038ff4330ca962e5d56641 |
|
MD5 | 888e0a069c52b507027b31a863f60b97 |
|
BLAKE2b-256 | 84975e2bfbcf42725ba5f64310423edcf00d90e684a61d55dd0a26b2313a44b6 |
哈希值 用于 maturin-1.7.4-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 23fae44e345a2da5cb391ae878726fb793394826e2f97febe41710bd4099460e |
|
MD5 | c077438ddae38850fc8c68b83c9df351 |
|
BLAKE2b-256 | 874352baa75e6dae9848ea22ae6bd405e7f7da091ba63409b07912048fde2083 |
哈希值 用于 maturin-1.7.4-py3-none-macosx_10_12_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 41a29c5b23f3ebdfe7633637e3de256579a1b2700c04cd68c16ed46934440c5a |
|
MD5 | d91a5ae2312acc165db3ea44153ff6d2 |
|
BLAKE2b-256 | 21dff75dcd8472f3be5b528942b11444eb4a82aa1aced7d105a8ba39bb85ece8 |
哈希值 用于 maturin-1.7.4-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 0182a9638399c8835afd39d2aeacf56908e37cba3f7abb15816b9df6774fab81 |
|
MD5 | 8a603b7200bce7b606fc7331083c24a4 |
|
BLAKE2b-256 | 4f0a1b2a2fda3f338dedd219de358d77b01f1138bc4bc6b4c73b6ea01d8ddd9e |