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

如何通过PyO3让Python访问Rust程序内的结构体实例?

实现Rust与Python的双向交互:让Python访问Rust Application实例

完全可行,你可以通过PyO3将Rust的Application实例引用传递给Python代码,让Python直接调用实例的方法来访问DocumentRepository。以下是具体实现方案:

1. 调整Rust代码,让Application可被Python识别

首先需要给Application添加#[pyclass]注解,同时确保相关类型满足线程安全要求(PyO3多线程调用需要Send+Sync trait),并暴露必要的方法给Python:

use pyo3::prelude::*;

// 假设Document已标记为PyO3可识别类型
#[pyclass]
struct Document {
    // 你的Document字段定义
}

#[pyclass]
struct DocumentRepository {
    database: postgres_database, // 需确保该类型实现Send + Sync
}

#[pymethods]
impl DocumentRepository {
    fn document(&self, name: String) -> PyResult<Document> {
        Ok(self.database.document(name))
    }
}

#[pyclass]
struct Application {
    document_repository: DocumentRepository,
}

#[pymethods]
impl Application {
    // 暴露给Python的方法,用于获取文档
    fn get_document(&self, name: String) -> PyResult<Document> {
        self.document_repository.document(name)
    }
}

impl Application {
    fn get_document_in_python(&self, name: String) -> PyResult<Document> {
        pyo3::prepare_freethreaded_python();
        
        Python::with_gil(|py| {
            // 加载外部Python代码
            let module = PyModule::from_code(
                py,
                include_str!("../python_code.py"),
                "example",
                "example"
            )?;
            
            // 获取Python中的get_document函数
            let get_doc_func: Py<PyAny> = module.getattr("get_document")?.into();
            
            // 将当前Application实例转换为Python可识别的对象
            let app_py = Py::new(py, self)?;
            
            // 调用Python函数,传入name和Application实例
            let doc_py: Py<Document> = get_doc_func.call1(py, (name, app_py))?.extract()?;
            
            // 将Python对象转换回Rust类型
            Ok(doc_py.extract(py)?)
        })
    }
}

// 手动实现线程安全trait(需确保内部成员确实支持跨线程访问)
unsafe impl Send for Application {}
unsafe impl Sync for Application {}

unsafe impl Send for DocumentRepository {}
unsafe impl Sync for DocumentRepository {}

2. 修改Python代码,接收并使用Application实例

Python代码直接接收name和app参数,调用Rust暴露的方法即可完成交互:

def get_document(name, app):
    # 调用Rust Application实例的方法获取文档
    document = app.get_document(name)
    return document

关键注意事项

  • 线程安全:必须确保Application、DocumentRepository及数据库连接类型实现Send和Sync,否则无法在多线程环境下通过PyO3传递实例。如果数据库连接本身不支持,可考虑用线程池封装连接逻辑。
  • 错误处理:示例中用PyResult替代了unwrap(),实际开发中应妥善处理错误,避免程序panic。
  • 类型兼容性:确保Document结构体已正确标记#[pyclass],PyO3会自动处理Rust与Python类型的双向转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:45:08