Python2.7中PyArrow转字符串为Binary问题求助(CSV转Parquet)
解决Python2.7下Pandas+PyArrow转Parquet时字符串变Binary的问题
我之前在Python2.7环境里处理CSV转Parquet时也踩过这个一模一样的坑——PyArrow总是把Pandas里的字符串列转成binary类型,导致AWS Glue完全没法正常解析。其实核心问题是Python2的str本质是字节类型,PyArrow默认会把它映射成binary,而不是AWS Glue需要的string(utf8)类型。你之前尝试自定义schema没生效,大概率是因为DataFrame里的列还是Python2的str类型,PyArrow转换时优先用数据的实际类型覆盖了你的schema。
下面是亲测有效的解决步骤:
1. 先把DataFrame的字符串列转为Python2的unicode类型
Python2的unicode是真正的字符串类型,PyArrow会把它正确识别为string(utf8),而不是binary。读取CSV后,遍历所有object类型的列(Pandas里字符串默认存在object列),把它们转成unicode:
import pandas as pd import pyarrow as pa from io import StringIO # 读取TSV文件 df = pd.read_csv(StringIO(file), delimiter="\t") # 转换所有object类型列为unicode,处理空值避免报错 for col in df.select_dtypes(include=['object']).columns: df[col] = df[col].apply(lambda x: unicode(x) if pd.notnull(x) else None)
2. 构造正确的自定义Schema并强制使用
现在构造schema时,把字符串列明确指定为pa.string(),然后在转换时强制传入这个schema,确保PyArrow按照我们期望的类型生成Parquet:
# 生成列类型映射:object列用pa.string(),其他列自动匹配numpy类型 dtype_mapping = {} for col in df.columns: if df[col].dtype == object: dtype_mapping[col] = pa.string() else: dtype_mapping[col] = pa.from_numpy_dtype(df[col].dtype) # 构建PyArrow schema fields = [pa.field(col_name, col_type) for col_name, col_type in dtype_mapping.items()] my_schema = pa.schema(fields) # 转换为PyArrow Table,强制使用自定义schema,忽略Pandas索引 table = pa.Table.from_pandas( df, schema=my_schema, preserve_index=False ) # 写入Parquet文件 table.write_to_file("output.parquet")
额外注意事项
- 确保你使用的PyArrow版本是支持Python2.7的较新版本(比如0.15.x到0.17.x,PyArrow从0.18开始不再支持Python2),旧版本的类型映射逻辑可能有bug。
- 如果你的CSV里有特殊字符,转换
unicode时可以指定编码(比如unicode(x, 'utf-8')),避免出现编码错误。
这样处理后,Parquet文件里的字符串列就会是string(utf8)类型,AWS Glue就能正常识别和处理了。
内容的提问来源于stack exchange,提问作者user5948130




