如何解决Polars读写含列表列的DataFrame到数据库的报错问题?
解决Polars读写SQLite含列表列DataFrame的问题
问题根源
SQLite本身没有原生的数组/列表数据类型,Polars写入列表列时会默认将其序列化为Blob二进制类型存储,但读取时无法自动将Blob解析回原列表结构,因此抛出Invalid column type Blob错误。
可行解决方案
方案1:将列表序列化为JSON字符串存储(推荐)
通过把列表列转为JSON字符串存入SQLite(TEXT类型),读取时再解析回列表,兼容性最好:
写入代码
import polars as pl import json # 创建DataFrame时将列表转为JSON字符串 df = pl.DataFrame({ 'a': [1, 2, 3], 'b': [json.dumps(lst) for lst in [['A','B'], ['C', 'D'], ['E', 'F']]] }) df.write_database( table_name="test", connection="sqlite:///test.db", if_table_exists="replace" )
读取代码
# 读取后将JSON字符串解析为列表 df_read = pl.read_database_uri( query="SELECT * FROM test", uri="sqlite://test.db" ).with_columns( pl.col('b').map_elements(json.loads, return_dtype=pl.List(pl.Utf8)) ) print(df_read)
方案2:借助SQLAlchemy自定义类型(需额外依赖)
如果想用SQLAlchemy的数组类型,需要安装sqlalchemy-utils扩展,同时SQLite需启用数组支持,配置相对繁琐:
import polars as pl from sqlalchemy import create_engine from sqlalchemy_utils import ArrayType # 创建指定类型的引擎 engine = create_engine("sqlite:///test.db") df.write_database( table_name="test", connection=engine, if_table_exists="replace", engine_options={ "dtype": {"b": ArrayType(str)} } ) # 读取时需指定解析逻辑 df_read = pl.read_database_uri( query="SELECT * FROM test", uri="sqlite://test.db" ).with_columns( pl.col('b').cast(pl.List(pl.Utf8)) )
说明
之前尝试的schema_overrides无效,是因为Polars读取时拿到的是Blob二进制数据,无法直接通过类型覆盖转换为列表,必须先解析Blob内容(或提前用JSON序列化避免Blob存储)。
内容的提问来源于stack exchange,提问作者Elis Evans
相关产品推荐
相关产品推荐

