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

如何使用boto3从S3读取CSV文件子集(解决内存溢出问题)

解决S3大CSV文件内存溢出问题:仅读取子集

你的问题根源在于obj.get()["Body"].read()会一次性把整个CSV文件下载到内存中,后续的islice只是在内存里截取子集,根本没解决内存占用问题。下面提供两种可靠的解决方案:

方案一:流式读取+逐行截取(推荐)

直接利用S3对象的流式响应,让csv.DictReader逐行读取,配合islice只取需要的行数,全程不会加载整个文件到内存:

import boto3
import csv
from itertools import islice
from io import TextIOWrapper

s3 = boto3.client('s3')
# 获取流式响应,避免一次性下载全量
response = s3.get_object(Bucket=bucket_name, Key=file_name)
# 将二进制流包装为UTF-8文本流
text_stream = TextIOWrapper(response['Body'], encoding='utf-8')
# 从流中截取前10行(包含CSV表头)
data = csv.DictReader(islice(text_stream, 10))

# 遍历读取到的子集数据
for row in data:
    print(row)

说明

  • response['Body']是可迭代的流对象,TextIOWrapper负责将二进制流转成文本流,csv.DictReader会逐行解析,islice会在读取到指定行数后停止,内存占用仅为当前行的大小。
  • 如果需要跳过表头、只取数据行,可以先手动读取表头行,再截取数据:
    # 先读取表头
    header = next(text_stream)
    # 取后续9条数据行
    data = csv.DictReader(islice(text_stream, 9), fieldnames=header.strip().split(','))
    

方案二:使用S3范围请求(精确控制下载字节)

如果需要精确控制下载的字节数(比如只下载前100KB),可以用S3的Range参数指定字节范围,避免下载全量文件:

import boto3
import csv
from io import StringIO

s3 = boto3.client('s3')
# 请求前10000字节(可根据实际情况调整范围)
response = s3.get_object(Bucket=bucket_name, Key=file_name, Range='bytes=0-9999')
content = response['Body'].read().decode('utf-8')

# 处理可能的不完整行:截断到最后一个换行符,保证CSV格式合法
last_newline = content.rfind('\n')
if last_newline != -1:
    content = content[:last_newline+1]

# 解析CSV子集
data = csv.DictReader(StringIO(content))
for row in data:
    print(row)

说明

  • Range参数的格式为bytes=start-end,比如bytes=0-9999表示下载第0到第9999字节(共10000字节)。
  • 由于CSV行可能跨字节范围,需要手动截断到最后一个换行符,避免解析不完整的行导致报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 18:32:53