读取S3返回的botocore.response.StreamingBody出现OverflowError如何解决
错误原因
该OverflowError: Python int too large to convert to C long报错的核心原因有两点:
- 当前使用的是32位版本Python,C long类型最大值仅为2^31-1(约2GB),当S3文件大小超过该阈值时,底层ssl/socket库尝试将文件大小转为C long就会触发报错
- 原代码连续三次调用
obj['Body'].read(),而botocore.response.StreamingBody是仅可消费一次的流式对象,就算第一次读取无报错,后续两次读取也只能拿到空数据,同时写入文件时使用了w文本模式,和read()返回的bytes类型不匹配,也会引发额外报错。
解决方案
方案1:分块读取,规避全量加载限制
不调用无参数read()一次性拉取全量数据,每次读取固定大小的块逐块处理,完全避免大长度int转换问题:
import boto3 import pandas as pd import io def get_cx_data(): """ Get cx data Returns: Pandas DataFrame: CX index DataFrame """ client = boto3.client('s3', aws_access_key_id = 'key_id_here', aws_secret_access_key = 'secret_key_here', region_name = 'us-east-2') obj = client.get_object( Bucket = 'bucket name', Key = 'key_here') # 每次读取10MB,可根据实际情况调整块大小 chunk_size = 10 * 1024 * 1024 # 方式1:先写入本地文件 with open('training_data.csv', 'wb') as f: while True: chunk = obj['Body'].read(chunk_size) if not chunk: break f.write(chunk) df_cx_index = pd.read_csv('training_data.csv') # 方式2:不需要本地文件的话,直接写入内存缓冲区 # buf = io.BytesIO() # while True: # chunk = obj['Body'].read(chunk_size) # if not chunk: # break # buf.write(chunk) # buf.seek(0) # df_cx_index = pd.read_csv(buf) print(df_cx_index.head()) return df_cx_index
方案2:使用boto3内置下载方法,无需手动处理流
boto3封装的download_fileobj底层已经实现了分块逻辑,不需要手动调用read()处理流式对象:
import boto3 import pandas as pd def get_cx_data(): """ Get cx data Returns: Pandas DataFrame: CX index DataFrame """ client = boto3.client('s3', aws_access_key_id = 'key_id_here', aws_secret_access_key = 'secret_key_here', region_name = 'us-east-2') # 直接下载到本地文件,无需手动操作StreamingBody with open('training_data.csv', 'wb') as f: client.download_fileobj('bucket name', 'key_here', f) df_cx_index = pd.read_csv('training_data.csv') print(df_cx_index.head()) return df_cx_index
方案3:根源修复
卸载当前32位Python,安装对应版本的64位Python,64位环境下C long的最大值远大于常规文件大小,不会触发该类型转换错误,可正常调用无参数read()读取全量流。
内容的提问来源于stack exchange,提问作者Jihjohn
相关产品推荐
相关产品推荐

