You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python读取S3二进制CSV文件乱码问题及解决方案咨询

问题:Lambda读取S3中CSV文件出现乱码,无法正确解析

Lambda函数以wb模式从邮件读取内容并上传CSV到S3,上传代码如下:

open('/tmp/' + filename, 'wb').write(part.get_payload(decode=True))
s3r.meta.client.upload_file('/tmp/' + filename)

读取时使用以下代码,但输出为乱码字节串:

client = boto3.client('s3')
data = client.get_object(Bucket=bucket_name, Key= key) 
with io.TextIOWrapper(data["Body"], encoding='latin1') as text_file:
    reader = csv.DictReader(text_file, delimiter=',')

    for row in reader:
        print(row)

乱码内容示例:

\x1bdº\x9e\x8f\x90dN\x18"m': '\x00\x80\x02\x00\x000\x8f\x18\x00\x00\x00', "à¥Ç\x9eDO97*\x82~§Èɸ8ÀOíc\x1c|n¦Ñ\x07ä\x04Eøÿ\x14ö\x11éºóÀB\x10ÉÀ!$}\x87íàÈé;{ìÐå[\x83îñ\x96é\x7f2þ\x06\x00\x00ÿÿ\x03\x00PK\x03\x04\x14\x00\x06\x00\x08\x00\x00\x00!\x00µU0#ô\x00\x00\x00L\x02\x00\x00\x0b\x00\x08\x02_rels/.rels ¢\x04\x02(\xa0\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00¬\x92MOÃ0\x0c\x86ïHü\x87È÷ÕÝ\x90\x10BKwAH»!T~\x80IÜ\x0fµ\x8d£$\x1bÝ¿'\x1c\x10T\x1a\x83\x03G\x7f½~üÊÛÝ<\x8dê

原因分析

乱码内容中出现PK标识,说明上传的并非纯CSV文件,而是ZIP压缩包。邮件附件可能本身是压缩后的ZIP格式(CSV被打包成ZIP作为附件),但当前代码直接将解码后的附件内容当作CSV写入并上传,导致S3存储的是ZIP文件,读取时按纯文本解析就会出现乱码。


解决步骤

1. 修正上传逻辑:先解压再上传CSV

如果邮件附件是ZIP包,需先解压获取内部的CSV文件,再上传至S3:

import zipfile
from io import BytesIO

# 读取邮件附件的二进制内容
payload = part.get_payload(decode=True)
# 将二进制内容包装为可读取的ZIP文件对象
zip_file = zipfile.ZipFile(BytesIO(payload))
# 获取ZIP内的第一个文件(假设仅包含目标CSV)
csv_filename = zip_file.namelist()[0]
# 读取CSV文件内容
csv_content = zip_file.read(csv_filename)

# 写入临时文件并上传到S3
with open('/tmp/' + csv_filename, 'wb') as f:
    f.write(csv_content)
s3r.meta.client.upload_file('/tmp/' + csv_filename, bucket_name, s3_key)

2. 修正读取逻辑:解压已上传的ZIP文件

如果S3中已经存储了ZIP文件,读取时需先解压再解析CSV:

import zipfile
from io import BytesIO
import csv
import boto3

client = boto3.client('s3')
data = client.get_object(Bucket=bucket_name, Key=key)
# 获取ZIP文件的二进制内容
zip_content = data["Body"].read()
# 解压ZIP文件
zip_file = zipfile.ZipFile(BytesIO(zip_content))
csv_filename = zip_file.namelist()[0]

# 读取并解析CSV,同时修改内容
with zip_file.open(csv_filename, 'r') as csv_file:
    # 根据CSV实际编码调整(如utf-8、gbk等)
    csv_lines = csv_file.read().decode('utf-8').splitlines()
    reader = csv.DictReader(csv_lines)
    
    for row in reader:
        # 示例:修改指定列的内容
        if 'old_value' in row['target_column']:
            row['target_column'] = row['target_column'].replace('old_value', 'new_value')
        print(row)

3. 可选:自动判断附件格式

上传前可先判断附件是否为ZIP,兼容纯CSV和压缩包两种情况:

import zipfile
from io import BytesIO

payload = part.get_payload(decode=True)
# 判断是否为ZIP文件
is_zip = zipfile.is_zipfile(BytesIO(payload))

if is_zip:
    # 按ZIP解压处理
    zip_file = zipfile.ZipFile(BytesIO(payload))
    csv_filename = zip_file.namelist()[0]
    csv_content = zip_file.read(csv_filename)
    with open('/tmp/' + csv_filename, 'wb') as f:
        f.write(csv_content)
    s3r.meta.client.upload_file('/tmp/' + csv_filename, bucket_name, s3_key)
else:
    # 按纯CSV直接上传
    with open('/tmp/' + filename, 'wb') as f:
        f.write(payload)
    s3r.meta.client.upload_file('/tmp/' + filename, bucket_name, s3_key)

内容的提问来源于stack exchange,提问作者Md. Parvez Alam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:45:53