如何在Python版AWS Lambda中返回io.BufferedReader并解决序列化报错
问题原因
- 报错的根本原因是AWS Lambda要求返回的响应必须是可JSON序列化的对象,你返回值里的
file字段直接放入了BufferedReader类型的文件句柄,这类Python内置IO对象没有默认的JSON序列化实现,直接触发了序列化失败错误。 - 代码同时存在两处逻辑隐患:
- 循环内每次覆盖写入同一个tmp文件,
body.append(f)写在了循环外部,只会追加最后一次循环的文件句柄到列表中 - 读取文件后不需要保留文件句柄在返回值内,直接处理文件内容即可
- 循环内每次覆盖写入同一个tmp文件,
修复方案
情况1:返回二进制文件内容供后续处理
如果你需要返回PDF这类二进制文件内容,需要转base64编码后才能支持JSON序列化,修复代码如下:
import boto3 import base64 s3 = boto3.client('s3') def lambda_handler(event, context): bucket = "bucketID" content_list = [] for record in event['key']: tmp_file_path = '/tmp/2021-10-11T06:23:29:691472.pdf' # 下载文件到临时目录 with open(tmp_file_path, 'wb') as f: s3.download_fileobj(bucket, "basedir/file.pdf", f) # 读取文件内容后自动释放句柄 with open(tmp_file_path, "rb") as f: file_content = f.read() # 二进制内容转base64编码,适配JSON序列化要求 content_list.append(base64.b64encode(file_content).decode('utf-8')) return { "statusCode": 200, # 移除文件句柄字段,仅返回可序列化的内容 "content_list": content_list }
情况2:读取JSON文件直接返回结构化内容
如果你实际读取的是JSON格式文件而非PDF,可以直接加载为JSON对象后返回:
import boto3 import json s3 = boto3.client('s3') def lambda_handler(event, context): bucket = "bucketID" json_content_list = [] for record in event['key']: tmp_file_path = '/tmp/target.json' with open(tmp_file_path, 'wb') as f: s3.download_fileobj(bucket, "basedir/file.json", f) # 直接加载JSON内容为Python原生字典/列表 with open(tmp_file_path, "r", encoding="utf-8") as f: json_data = json.load(f) json_content_list.append(json_data) return { "statusCode": 200, "content": json_content_list }
核心注意点
- 禁止将Python IO对象(文件句柄、连接句柄等)直接放入Lambda返回值
- 所有二进制内容必须转base64编码后才能进行JSON序列化
- 建议使用
with上下文管理器操作文件,自动关闭句柄避免资源泄漏
内容的提问来源于stack exchange,提问作者SREERAG R NANDAN
相关产品推荐
相关产品推荐

