使用pyo3将含字典的Polars DataFrame从Python转Rust时出错
Polars Python转Rust时Object类型转换失败
问题背景
通过Python创建包含字典的Polars DataFrame,Python环境运行正常,但通过pyo3的extract方法转换到Rust环境时触发错误。
复现代码
Rust代码
use pyo3::prelude::*; use pyo3_polars::*; let code = r#" import polars as pl import pandas as pd df = pd.DataFrame({ "the_column": [{ "key" : 123 }, { "foo" : 456 }, { "bar" : 789 }]}) schema = pl.from_pandas(df.head(1)).schema | {"the_column": pl.Object} result = pl.DataFrame(df.to_dict("records"), schema=schema) "#; Python::with_gil(|py| { let globals = py.import("builtins").unwrap().dict(); py.run(code, Some(globals), None).unwrap(); let result = globals.get_item("result").unwrap(); let PyDataFrame(_df) = result.extract().unwrap(); });
Python逻辑说明
先通过Pandas创建包含字典的DataFrame,再手动指定列类型为pl.Object,转换为Polars DataFrame。
错误信息
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: InvalidOperation(Owned("Cannot create polars series from FixedSizeBinary(8) type"))'
依赖配置(Cargo.toml)
polars = { version = "~0.27.2", features = ["object", "dtype-full"] }
解决方案
问题根源是pyo3-polars对Python端定义的pl.Object类型转换支持存在兼容性问题,可通过以下两种方式解决:
方案1:直接转换,不手动指定Object类型
修改Python代码逻辑,去掉手动指定pl.Object的步骤,让Polars自动推断类型:
import polars as pl import pandas as pd df = pd.DataFrame({ "the_column": [{ "key" : 123 }, { "foo" : 456 }, { "bar" : 789 }]}) # 直接从Pandas转换为Polars DataFrame result = pl.from_pandas(df)
方案2:序列化JSON字符串后再转换
如果需要明确保留字典结构,可先将字典序列化为JSON字符串,在Rust端再反序列化:
修改后的Python代码
import polars as pl import pandas as pd import json df = pd.DataFrame({ "the_column": [{ "key" : 123 }, { "foo" : 456 }, { "bar" : 789 }]}) # 将字典转为JSON字符串 df["the_column"] = df["the_column"].apply(json.dumps) result = pl.from_pandas(df)
Rust端处理代码
use polars::prelude::*; use serde_json::Value; // 提取DataFrame后处理JSON字符串列 let json_series = _df.column("the_column").unwrap(); let dict_values: Vec<Option<Value>> = json_series .utf8() .unwrap() .into_iter() .map(|s| s.map(|s_str| serde_json::from_str(s_str).unwrap())) .collect();
内容的提问来源于stack exchange,提问作者GrantS
相关产品推荐
相关产品推荐

