Python 3.12在AWS Lambda导出含中文CSV至Excel失败求助
解决AWS Lambda中Python生成中文CSV在Excel乱码及SES邮件附件问题
核心问题分析
- Excel通过「数据>自文本导入」时,若CSV的UTF-8 BOM未正确生成或传递,会默认用系统编码(如GBK)解析导致乱码
msg.as_string()会将邮件内容转换为7-bit ASCII编码,破坏UTF-8 BOM及特殊字符(如表情)的二进制结构
分步解决方案
1. 确保MySQL数据读取时编码正确
连接MySQL必须指定utf8mb4字符集,避免数据在读取阶段就出现乱码:
import mysql.connector db_conn = mysql.connector.connect( host="your-mysql-host", user="your-user", password="your-password", database="your-db", charset="utf8mb4" ) cursor = db_conn.cursor(dictionary=True) cursor.execute("SELECT * FROM your_target_table") data_rows = cursor.fetchall()
2. 生成带正确UTF-8 BOM的CSV
直接通过字节流写入BOM,再用标准csv模块生成内容,避免手动写入BOM被当作文本:
import csv import io # 创建字节流对象,先写入UTF-8 BOM csv_buffer = io.BytesIO() csv_buffer.write(b'\xef\xbb\xbf') # UTF-8 BOM标记 # 以UTF-8编码写入CSV内容 writer = csv.writer(csv_buffer, dialect="excel") # 写入表头 writer.writerow(data_rows[0].keys()) # 写入数据行 for row in data_rows: writer.writerow(row.values()) # 重置指针到开头,准备读取字节 csv_buffer.seek(0) csv_bytes = csv_buffer.getvalue()
3. SES邮件附件正确编码传递
避免使用msg.as_string(),改用msg.as_bytes()保留二进制编码,同时正确设置附件的Content-Type:
import boto3 from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.application import MIMEApplication # 初始化SES客户端 ses_client = boto3.client("ses", region_name="your-aws-region") # 构建邮件主体 msg = MIMEMultipart() msg["Subject"] = "中文数据CSV附件" msg["From"] = "sender@example.com" msg["To"] = "recipient@example.com" # 添加邮件正文 email_body = MIMEText("请查收附件的中文数据CSV文件", "plain", "utf-8") msg.attach(email_body) # 添加CSV附件 csv_attachment = MIMEApplication(csv_bytes, _subtype="csv") csv_attachment.add_header("Content-Disposition", "attachment", filename="data.csv") csv_attachment.add_header("Content-Type", "text/csv; charset=utf-8-sig") msg.attach(csv_attachment) # 发送邮件,传递原始字节流 response = ses_client.send_raw_email( Source=msg["From"], Destinations=[msg["To"]], RawMessage={"Data": msg.as_bytes()} )
关键注意事项
- Excel导入时,若手动选择编码,务必选「UTF-8」而非「UTF-8 BOM」(Excel会自动识别BOM)
- Lambda中临时文件可写入
/tmp目录,但使用字节流比文件更高效,避免IO开销 - 测试时可将CSV字节保存到S3,下载后本地验证编码,排除SES传递前的问题
内容的提问来源于stack exchange,提问作者Ellery Leung
相关产品推荐
相关产品推荐

