如何通过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
相关产品推荐
相关产品推荐

