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

AWS Lambda使用tempfile将字符串写入CSV上传S3报错如何解决

报错原因
  • 核心错误是对tempfile.TemporaryFile的用法错误:tempfile.TemporaryFile()的返回值本身就是可直接读写的文件类对象,不是本地文件路径字符串,不需要再调用open()去打开它,给open()传文件对象自然会触发类型不匹配的报错。
  • 同时存在3个隐藏问题:
    1. 代码头部缺少os、io、openpyxl的导入声明,运行时会触发模块未找到错误
    2. s3.put_object()的调用参数错误,文件内容需要传给Body参数,不能直接把文件对象作为第一个位置参数传入
    3. 拼接完的CSV字符串直接写入即可,不需要逐字符遍历写入,属于冗余操作
可行修复方案

你可以根据场景选择两种写法,修正后的完整代码如下:

import csv
import boto3
import urllib3
import tempfile
import os
import io
import openpyxl

s3 = boto3.client('s3')
bucket = os.environ['S3_BUCKET']
http = urllib3.PoolManager()

# 此处补充你未提供的readS3实现,若已有可删除
def readS3(key):
    resp = s3.get_object(Bucket=bucket, Key=key)
    return resp['Body'].read()

def lambda_handler(event, context):
    file = readS3('example.xlsx')
    latest_scan = openpyxl.load_workbook(io.BytesIO(file), data_only=True)
    sh = latest_scan.active

    csv_lines = []
    for row in sh['A']:
        if not row.value:
            continue # 跳过空行避免接口请求错误
        r5 = http.request(
            'GET',
            f'https://example.com/api/{row.value}',
            headers={
                'Accept': 'text/csv'
            }
        )
        csv_lines.append(r5.data.decode('utf-8'))
    
    full_csv = ''.join(csv_lines)

    # 方案1:保留临时文件逻辑的正确写法
    with tempfile.TemporaryFile(mode='w+', encoding='utf-8', suffix='.csv') as temp:
        temp.write(full_csv)
        temp.seek(0)
        s3.put_object(Body=temp.read(), Bucket=bucket, Key='test.csv')
    
    # 方案2:数据量小的场景下更简化的写法,无需临时文件,直接上传字节
    # s3.put_object(Body=full_csv.encode('utf-8'), Bucket=bucket, Key='test.csv')

主要改动点:

  • 补全了缺失的依赖模块导入,补充了readS3的基础实现
  • 移除了错误的嵌套open()调用,直接操作TemporaryFile返回的文件对象
  • 修正了s3.put_object的传参格式,显式指定Body参数接收上传内容
  • 增加空行判断逻辑,避免空单元格导致接口请求路径异常
  • 移除冗余的逐字符写入逻辑,直接写入完整CSV字符串提升效率

内容的提问来源于stack exchange,提问作者Kostas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 19:54:03