如何分离Rust库与其包装的PyO3导出Python扩展?
我有一个用Rust写的库,它提供了一些在其他Rust程序中很有用的功能。此外,我还想把这些功能作为Python的扩展提供(使用pyo3和setuptools-rust,虽然大部分工具是通用的)。
文档中的例子都展示了一个单一的库。这意味着,任何构建这个Rust库并在Rust生态系统中使用它的人,都需要Python的头文件,并且还会得到导出的Python模块。
我该如何将这个库分开,使它成为一个独立的Rust库,提供Rust中的功能,同时又有一个Python包,提供Python中的功能呢?
1 个回答
-1
经过一些实验,我找到了一个使用 Rust 工作区的设置:
目录结构:
FizzBuzz
- fizzbuzz
- src
- lib.rs
- tests
- test_....rs
...
- Cargo.toml
- fizzbuzzo3
- src
- lib.rs
- Cargo.toml
- fizzbuzzpy
- fizzbuzzpy
- __init__.py
- fizzbuzzer.py
- tests
- test_fizzbuzzo3.py
- test_fizzbuzzpy.py
- Cargo.toml
- pyproject.toml
其中:
fizzbuzz
目录包含纯 Rust 的实现fizzbuzzo3
目录包含为 Python 封装的 pyo3 版本fizzbuzzpy
目录包含额外的原生 Python 功能和 pytest 测试
配置文件:
fizzbuzz/Cargo.toml
[package]
name = "fizzbuzz"
version = "0.2.1"
edition = "2021"
[lib]
name = "fizzbuzz"
path = "src/lib.rs"
crate-type = ["rlib"] # cdylib required for python import, rlib required for rust tests.
fizzbuzzo3/Cargo.toml
[package]
name = "fizzbuzzo3"
version = "0.1.0"
edition = "2021"
[lib]
name = "fizzbuzzo3"
path = "src/lib.rs"
crate-type = ["cdylib"] # cdylib required for python import, rlib required for rust tests.
[dependencies]
pyo3 = { version = "0.21.0-beta.0" }
fizzbuzz = { path = "../fizzbuzz" }
./Cargo.toml
[workspace]
members = [
"fizzbuzz",
"fizzbuzzo3"
]
resolver = "2"
pyproject.toml
[build-system]
requires = ["setuptools", "setuptools-rust"]
build-backend = "setuptools.build_meta"
[project]
name = "fizzbuzz"
description = "An implementation of the traditional fizzbuzz kata"
...
[tool.setuptools.packages.find]
where = ["fizzbuzzpy"]
[[tool.setuptools-rust.ext-modules]]
# Private Rust extension module to be nested into the Python package
target = "fizzbuzzo3" # The last part of the name (e.g. "_lib") has to match lib.name in Cargo.toml,
# but you can add a prefix to nest it inside of a Python package.
path = "fizzbuzzo3/Cargo.toml" # Default value, can be omitted
binding = "PyO3" # Default value, can be omitted
[project.optional-dependencies]
dev = [
"black",
"pytest",
"pytest-doctest-mkdocstrings",
"ruff",
]
如何操作:
- 构建并测试纯 Rust 实现:
~/Fizzbuzz/fizzbuzz$ cargo test -v
- 构建并单元测试 Python 绑定:
~/Fizzbuzz/fizzbuzzo3$ cargo test -v
- 运行所有 Rust 测试:
~/Fizzbuzz$ cargo test -v
- 在 Python 中构建、安装并测试 Rust 绑定:
(.venv) ~/Fizzbuzz$ pip install -e .[dev] && pytest
如果你想更详细地了解完整的代码库,可以查看: MusicalNinjaDad/FizzBuzz