如何在Rust中处理Python字典类型?
嘿,我来帮你捋清楚怎么用Rust的pyo3库处理Python字典!你提到已经尝试了Py<PyDict>,其实还有几种更贴合不同场景的写法,我给你逐一说明:
直接借用Python字典(最常用的方式)
如果你只是需要读取Python传过来的字典,不用持有它的所有权,直接用&PyDict作为参数就好,这样不用额外处理所有权逻辑,操作起来更顺手:use pyo3::prelude::*; use pyo3::types::PyDict; #[pyfunction] fn process_dict(map: &PyDict) -> PyResult<String> { // 遍历字典的键值对,把Python类型转成Rust类型 for (key, value) in map.iter() { let key_str: &str = key.extract()?; let value_int: i32 = value.extract()?; println!("键: {}, 值: {}", key_str, value_int); } Ok("处理完成".to_string()) }这里的
extract()方法会自动帮你把Python的键值转换成对应的Rust类型,如果类型不匹配(比如Python传了字符串但你要整数),会自动返回PyErr,不用你手动处理错误判断。自动转成Rust的HashMap(纯Rust风格操作)
如果你想在Rust里用最熟悉的HashMap来操作数据,pyo3支持自动把Python字典转换成Rust的HashMap,前提是字典的键值类型能和Rust类型对应上:use pyo3::prelude::*; use std::collections::HashMap; #[pyfunction] fn process_dict(map: HashMap<String, i32>) -> PyResult<String> { // 直接用Rust HashMap的所有方法操作 if let Some(val) = map.get("a") { println!("键a对应的值是: {}", val); } Ok("处理完成".to_string()) }这种方式的好处是,你可以完全用Rust的集合操作逻辑来处理数据,不用关心Python对象的GIL细节,非常适合需要复杂数据处理的场景。
处理带所有权的
Py<PyDict>
如果你确实需要持有Python字典的所有权(比如要把它传递到其他需要所有权的函数里),你原来用的Py<PyDict>是可行的,但需要先把它转换成借用的&PyDict才能操作,因为Python对象必须在GIL保护下访问:use pyo3::prelude::*; use pyo3::types::PyDict; #[pyfunction] fn process_dict(map: Py<PyDict>) -> PyResult<String> { // 在GIL上下文下把Py<PyDict>转成借用引用 Python::with_gil(|py| { let dict = map.as_ref(py); for (key, value) in dict.iter() { let key: &str = key.extract()?; let value: i32 = value.extract()?; println!("{}: {}", key, value); } Ok("处理完成".to_string()) }) }把Rust数据转回Python字典
要是你需要从Rust函数返回字典给Python,也有两种简单的方式:
一种是直接返回Rust的HashMap,pyo3会自动转成Python字典:use pyo3::prelude::*; use std::collections::HashMap; #[pyfunction] fn return_dict() -> PyResult<HashMap<String, i32>> { let mut map = HashMap::new(); map.insert("a".to_string(), 1); map.insert("b".to_string(), 2); Ok(map) }另一种是直接创建Python的
PyDict对象返回,适合需要精细控制Python对象的场景:use pyo3::prelude::*; use pyo3::types::PyDict; #[pyfunction] fn return_dict(py: Python<'_>) -> PyResult<&PyDict> { let dict = PyDict::new(py); dict.set_item("a", 1)?; dict.set_item("b", 2)?; Ok(dict) }
内容来源于stack exchange

