AWS Lambda Python脚本读取S3 CSV全量行但写入输出行数缺失
AWS Lambda CSV写入S3行数缺失问题解决方案
核心成因
- 最核心原因:文件上传操作时机错误。当前代码将
upload_file方法放在with open上下文块内部,此时文件仍处于打开状态,Python与操作系统的IO缓冲区中还有部分未刷入磁盘的内容,上传的文件仅包含已经写入磁盘的部分,直接导致行数缺失。 - 第二大原因:代码缩进错误。你提供的原始代码中,输出文件读取计数、return语句均位于
lambda_handler函数外部,Lambda运行时仅会执行函数内的逻辑,外部代码会在冷启动阶段执行,此时要么还未生成输出文件,要么读取的是上一次运行的旧文件,导致计数结果异常。 - 小概率原因:/tmp目录空间不足,不过2万多行的CSV文件远小于Lambda默认提供的512MB临时空间,该情况可以优先排除。
排查步骤
- 检查代码缩进:确认文件上传、输出计数、返回值逻辑全部在
lambda_handler函数内部。 - 在CloudWatch日志中打印上传前本地临时文件的大小,以及S3上输出文件的元数据大小,若两者不一致即可确认是上传时文件未完全写入导致的问题。
- 可在上传前先调用
file.flush()+os.fsync(file.fileno())强制刷入缓冲区,验证行数是否恢复正常。
解决方法
修正后的代码如下:
import json import os import io import boto3 import csv import time def lambda_handler(event, context): s3 = boto3.resource(u's3') s3_object_in = s3.Object('MYBUCKET', 'INPUT.csv') data_in = s3_object_in.get()['Body'].read().decode('utf-8').splitlines() lines = csv.reader(data_in, delimiter=',') lambda_path = "/tmp/temp.csv" i_in=0 # 写入本地临时文件 with open(lambda_path, 'w+', encoding="utf-8") as file: for line in lines: file.write(str(i_in)+ '\n') i_in += 1 # 退出with块后文件已自动关闭,缓冲区全部刷入磁盘,此时再上传 s3.Bucket('MYBUCKET').upload_file(lambda_path, 'out.csv') # 计数输出文件行数,逻辑放在函数内部 s3_object_out = s3.Object('MYBUCKET', 'out.csv') data_out = s3_object_out.get()['Body'].read().decode('utf-8').splitlines() lines_out = csv.reader(data_out) i_out=0 for line in lines_out: i_out += 1 return { 'count_in': i_in, 'count_out': i_out }
修正点说明:
- 将S3上传操作移动到
with open块外部,确保文件关闭、内容完全写入磁盘后再上传 - 调整代码缩进,将输出文件计数、return语句全部放在
lambda_handler函数内部 - 移除冗余的
file.close()语句,with上下文管理器会自动处理文件关闭
内容的提问来源于stack exchange,提问作者Guilherme Louzada
相关产品推荐
相关产品推荐

