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

Python+boto3遍历S3存储桶gzip文件第二次迭代报文件不存在错误

报错核心原因

你的代码逻辑存在本质错误:从未实际从S3下载文件,一直尝试读取本地文件系统的文件:

  • list_objects_v2接口仅返回S3存储桶内的对象元数据列表,不会自动将对象文件下载到代码运行的机器本地
  • 你通过os.path.split(content["Key"])[-1]拿到的只是S3对象的文件名(比如part-r-00001.gz),不是本地真实存在的文件路径
  • 第一次迭代能正常运行纯粹是巧合:你的代码运行工作目录下刚好存在一个同名的part-r-00000.gz本地文件,gzip实际读取的是这个本地文件,根本不是S3上存储的对象;第二个文件在本地没有对应同名文件,直接触发「文件不存在」报错
  • 你后续调整的gzip.GzipFile实现没有修复核心问题,仍然在尝试读取本地路径,因此报错不会消失。

对应报错日志如下:

2022-06-18 12:14:48,027 [root] INFO ----- starting with file:
part-r-00001.gz ----- 2022-06-18 12:14:48,028 [root] ERROR [Errno 2]
No such file or directory: 'part-r-00001.gz'

正确实现方案

推荐直接读取S3返回的字节流,无需将文件落盘到本地,同时补充了分页处理逻辑(list_objects_v2默认单次最多返回1000个对象,不分页会漏读文件),代码如下:

import boto3
import gzip
from datetime import datetime, timedelta
import logging
import sys

logger = logging.getLogger(__name__)
BUCKET = 'bucket'
PREFIX = 'path'

now = datetime.utcnow()
today = (now - timedelta(days=2)).strftime('%Y-%m-%d')
folder_of_the_day = PREFIX + today + '/'
logger.info("map folder: %s", folder_of_the_day)

client = boto3.client('s3')
# 初始化分页器遍历所有对象
paginator = client.get_paginator('list_objects_v2')
page_iterator = paginator.paginate(Bucket=BUCKET, Prefix=folder_of_the_day)

for page in page_iterator:
    for content in page.get('Contents', []):
        object_key = content["Key"]
        bucket_file = object_key.split('/')[-1]
        if bucket_file.endswith('.gz'):
            logger.info("----- starting with file: %s -----", bucket_file)
            try:
                # 拉取S3对象流
                s3_resp = client.get_object(Bucket=BUCKET, Key=object_key)
                # 直接对流做gzip解压,逐行读取
                with gzip.open(s3_resp['Body'], mode="rt", encoding='utf-8') as f:
                    for line in f:
                        # 写入你的行处理逻辑
                        pass
            except Exception as e:
                logger.error(e)
                logger.critical("Failed to open file!")
                sys.exit(4)

可选方案:先下载到本地再读取

如果你有文件落盘需求,必须显式调用下载接口把S3文件存储到本地路径,再读取本地文件,示例代码片段:

if bucket_file.endswith('.gz'):
    local_tmp_path = f"/tmp/{bucket_file}"
    # 显式将S3对象下载到本地临时路径
    client.download_file(BUCKET, object_key, local_tmp_path)
    with gzip.open(local_tmp_path, mode="rt", encoding='utf-8') as f:
        for line in f:
            # 写入你的行处理逻辑
            pass

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:18:27