尽管使用UTF8编码,S3输出仍出现'Â'字符的问题排查
从S3读取CSV写入后出现大量'Â'字符的编码问题解决
我在Glue Notebook中执行任务:从S3拉取多个CSV文件,格式化合并后推回S3。但输出文件中出现大量Â字符,即使仅读取后直接写回,空格等位置也会出现该字符,推测问题出在write_to_s3函数的编码设置上。
现有代码
读取与合并代码
import pandas as pd import numpy as np import boto3 import io s3_client = boto3.client("s3") S3_BUCKET_NAME = "bucket" S3_PREFIX_Manufacturer = "Cost/Data_Source/Manufacturer" def read_from_s3(object_key): file_content = s3_client.get_object(Bucket=S3_BUCKET_NAME, Key=object_key)["Body"].read() return pd.read_csv(io.BytesIO(file_content), header=0) data = pd.DataFrame() # 示例仅用单个文件,函数支持多文件合并 manuf_data = ["Manufacturer_Report_(Jan5)_UTF8.csv"] for manuf in manuf_data: object_key = f"{S3_PREFIX_Manufacturer}/{manuf}" df = read_from_s3(object_key) data = pd.concat([data, df])
写入S3代码
def write_to_s3(df, bucket, key): body = df.to_csv(index=False, encoding="cp1252") # 曾尝试encoding="utf-8-sig" s3_client.put_object(Body=body, Bucket=bucket, Key=key) processed_key = "Cost/Data_Source/Manufacturer/test.csv" write_to_s3(data, S3_BUCKET_NAME, processed_key)
输入输出示例
输入CSV内容
| Part Number | Manufacturers | Manufacturer Code |
|---|---|---|
| 112000 | Zebra ~ Elephant | ZX123 ~ XY45 |
| 113000 | Giraffe ~ Lion ~ Tiger | ABC-123 ~ 300100 ~ TIGER 23 |
| 114000 | No Manufacturer Given | No Manufacturer Given |
写入后输出CSV内容
| Part Number | Manufacturers | Manufacturer Codes |
|---|---|---|
| 112000 | Zebra ~ Elephant, Inc | ZX123 ~ XY45 |
| 113000 | Giraffe Co. ~ Lion ~ Tiger Corp. | ABC-123 ~ 300100 ~ TIGER 23 |
| 114000 | No Manufacturer Given | No Manufacturer Given |
问题原因与解决方法
Â字符是典型的编码不匹配导致的乱码:UTF-8编码的多字节字符(如非标准空格0xC2A0)被当作单字节编码(如CP1252)解析时,会拆分出Â字符。结合你的场景,问题出在读取和写入的编码一致性上:
1. 读取时明确指定UTF-8编码
源文件名包含UTF8,说明文件是UTF-8编码(可能带BOM),读取时需明确指定编码,避免pandas使用系统默认编码读取:
def read_from_s3(object_key): file_content = s3_client.get_object(Bucket=S3_BUCKET_NAME, Key=object_key)["Body"].read() # 指定UTF-8编码读取,处理可能的BOM return pd.read_csv(io.BytesIO(file_content), header=0, encoding="utf-8-sig")
2. 写入时直接输出字节流,避免编码二次转换
原代码中df.to_csv(encoding="cp1252")生成CP1252编码的字符串,传递给put_object时Python会自动将其编码为UTF-8字节流,导致二次编码乱码。改用字节流直接写入,确保编码一致:
def write_to_s3(df, bucket, key): # 生成UTF-8带BOM的字节流,直接写入S3 buffer = io.BytesIO() df.to_csv(buffer, index=False, encoding="utf-8-sig") buffer.seek(0) # 重置流指针到开头 s3_client.put_object(Body=buffer, Bucket=bucket, Key=key)
原理说明
utf-8-sig编码会自动处理UTF-8文件的BOM头,确保读取和写入时字符解析正确;- 使用
BytesIO直接生成字节流,跳过字符串到字节的转换步骤,避免Python默认编码干扰,保证写入的字节流与指定编码完全一致。
内容的提问来源于stack exchange,提问作者silliw
相关产品推荐
相关产品推荐

