使用boto3读取Parquet文件时日期格式丢失及字符乱码问题
解决S3 Select读取Parquet时的日期格式与字符乱码问题
嘿,我来帮你搞定这两个头疼的问题——这俩都是用S3 Select读Parquet文件时常见的坑,咱们一步步来解决:
问题根源拆解
- 日期变超大数字:你的Parquet里的
fecha_instalacion是纳秒级时间戳存储的,S3 Select默认不会自动把这个原始整数值转换成人类可读的日期格式,直接返回了底层的数字。 - 字符乱码(比如ESPAÃA):这是因为你用
ISO-8859-1解码,但文件本身是UTF-8编码的,多字节字符(比如西班牙语的Ñ)被错误解码就会变成乱码。
分步解决办法
1. 先搞定字符乱码
把解码用的编码从ISO-8859-1改成utf-8就行,一行代码的事儿:
string_csv = rl0['Records']['Payload'].decode('utf-8')
另外提醒下:有时候S3 Select的Payload可能会分成多个Records块,最好遍历所有事件拼接内容,避免遗漏数据,我后面的完整代码会加上这个处理。
2. 把超大数字转成正确日期
在S3 Select的SQL语句里,咱们得显式把时间戳转成可读日期。从你给出的数字来看,这是纳秒级的时间戳,所以用TO_TIMESTAMP函数的时候要除以10^9转成秒级:
Expression=f"select TO_TIMESTAMP(fecha_instalacion / 1000000000) as fecha_instalacion, pais from s3object s ",
如果转出来日期不对,可能是你的时间戳是毫秒/微秒级的,调整除数就行:毫秒级用/1000,微秒级用/1000000。要是还是不行,直接试试CAST成TIMESTAMP类型:
Expression=f"select CAST(fecha_instalacion AS TIMESTAMP) as fecha_instalacion, pais from s3object s ",
完整修正后的代码
我把所有调整都整合进去了,还加了Payload的完整处理逻辑:
import boto3 from io import StringIO import pandas as pd boto_s3 = boto3.client('s3') r = boto_s3.select_object_content( Bucket='bucket_name', Key='path/file.gz.parquet', ExpressionType='SQL', # 这里用纳秒转秒的TO_TIMESTAMP,根据实际情况调整 Expression=f"select TO_TIMESTAMP(fecha_instalacion / 1000000000) as fecha_instalacion, pais from s3object s ", InputSerialization={'Parquet': {}}, OutputSerialization={'CSV': {}}, ) # 遍历所有Payload事件,拼接所有Records内容 csv_content = [] for event in r['Payload']: if 'Records' in event: csv_content.append(event['Records']['Payload'].decode('utf-8')) # 合并成完整的CSV字符串 string_csv = ''.join(csv_content) csv = StringIO(string_csv) df = pd.read_csv(csv, names=['fecha_instalacion', 'pais']) print(df)
额外小技巧
如果后续解析CSV还有问题,可以在OutputSerialization里明确指定CSV的格式参数,比如分隔符、引号等:
OutputSerialization={ 'CSV': { 'FieldDelimiter': ',', 'QuoteCharacter': '"', 'RecordDelimiter': '\n' } },
内容的提问来源于stack exchange,提问作者GabyLP
相关产品推荐
相关产品推荐

