You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何分离Rust核心库与PyO3封装的Python扩展及测试方案

问题解答

1. 拆分核心功能与Python绑定的最佳实践(Cargo工作区方案)

你的猜测完全正确,Cargo工作区是这类场景的最优解,能彻底分离Rust核心库和Python绑定层,让Rust用户无需依赖Python生态,同时Python用户仅需安装绑定包即可使用功能。

最终项目结构

FizzBuzz/
├── Cargo.toml          # 工作区根配置
├── pyproject.toml      # Python打包配置
├── fizzbuzz-core/      # Rust核心功能库
│   ├── Cargo.toml
│   ├── src/
│   │   └── lib.rs
│   └── tests/
│       └── test_fizzbuzz.rs
└── fizzbuzz-py/        # Python绑定层Rust库
    ├── Cargo.toml
    ├── src/
    │   └── lib.rs
    └── tests/
        ├── test_fizzbuzzo3.rs  # Rust侧测试绑定逻辑
        └── test_fizzbuzz.py    # Python侧测试功能

关键配置细节

根Cargo.toml(工作区)

[workspace]
members = ["fizzbuzz-core", "fizzbuzz-py"]

fizzbuzz-core/Cargo.toml(核心库)

仅保留Rust生态所需配置,完全脱离PyO3依赖:

[package]
name = "fizzbuzz-core"
version = "0.1.0"
edition = "2021"

[dependencies]
# 只添加核心功能需要的Rust依赖,无PyO3相关配置

fizzbuzz-py/Cargo.toml(绑定层)

依赖核心库和PyO3,指定编译为Python扩展格式:

[package]
name = "fizzbuzz-py"
version = "0.1.0"
edition = "2021"

[dependencies]
fizzbuzz-core = { path = "../fizzbuzz-core" }
pyo3 = { version = "0.21", features = ["extension-module"] }

[lib]
name = "fizzbuzz_py"  # Python导入时的模块名(需用下划线)
crate-type = ["cdylib"]

pyproject.toml(Python打包)

配置setuptools-rust指向绑定层项目:

[build-system]
requires = ["setuptools", "setuptools-rust"]
build-backend = "setuptools.build_meta"

[project]
name = "fizzbuzz-py"
version = "0.1.0"
dependencies = []

[tool.setuptools-rust]
extension = true
rust-version = "1.70"
path = "fizzbuzz-py/Cargo.toml"

优势与发布流程

  • 核心库fizzbuzz-core可独立发布到crates.io,Rust用户直接通过cargo add fizzbuzz-core使用,完全不涉及Python依赖。
  • Python绑定包fizzbuzz-py通过python -m build构建后,可发布到PyPI,Python用户用pip install fizzbuzz-py安装。
  • 修改核心库代码后,工作区会自动同步依赖,三个测试套件(核心库Rust测试、绑定层Rust测试、Python测试)都能感知变更,直接运行对应测试命令即可。

2. 无需pip install即可测试Python扩展的方案

方案1:用PyO3在Rust中直接测试绑定

在fizzbuzz-py/tests/test_fizzbuzzo3.rs中,利用PyO3的Python上下文直接调用导出的函数,无需安装扩展:

use pyo3::prelude::*;

#[test]
fn test_fizzbuzz_py() -> PyResult<()> {
    let gil = Python::acquire_gil();
    let py = gil.python();

    // 导入当前构建的绑定模块
    let fizzbuzz_py = py.import("fizzbuzz_py")?;
    let result: String = fizzbuzz_py.call_method1("fizzbuzz", (15,))?.extract()?;
    
    assert_eq!(result, "FizzBuzz");
    Ok(())
}

运行测试:

cd fizzbuzz-py
cargo test

方案2:直接加载构建好的动态库进行Python测试

先构建绑定层:

cd fizzbuzz-py
cargo build --release

在Python测试文件中添加动态库路径,直接导入测试:

import sys
import os

# 根据系统动态添加库路径
lib_dir = os.path.join(os.path.dirname(__file__), "../target/release")
sys.path.append(lib_dir)

import fizzbuzz_py

def test_fizzbuzz():
    assert fizzbuzz_py.fizzbuzz(15) == "FizzBuzz"

直接运行Python测试:

python fizzbuzz-py/tests/test_fizzbuzz.py

方案3:用maturin简化测试(可选替代setuptools-rust)

如果切换到maturin工具,可直接完成构建并测试,无需手动安装:

# 临时构建并加载扩展到当前环境,不修改全局依赖
maturin develop --release
# 运行Python测试
pytest fizzbuzz-py/tests/

或者用maturin test一键执行所有测试(包括Rust和Python测试):

maturin test

内容的提问来源于stack exchange,提问作者MusicalNinja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 12:50:56