如何使用Python读取zip压缩包内的超大CSV文件?
解决方案
方案1:pandas分块读取(无需额外依赖)
你之前的写法错误在于循环逐行读取时重复创建DataFrame,且直接将文件流传入DataFrame的逻辑不符合pandas的读取规则。正确的分块读取写法如下:
import pandas as pd import zipfile # 单次处理单个zip文件 chunk_size = 100000 # 每次读取的行数,可根据自身内存大小调整 all_chunk_res = [] # 若需要合并全量结果可加,不需要则直接逐块处理 with zipfile.ZipFile('Events_WE20200308.zip', 'r') as z: with z.open('Events_WE20200308.csv') as f: # 按块读取csv,直接传入文件流即可 for chunk in pd.read_csv(f, chunksize=chunk_size, dtype={ # 按需指定列类型,大幅降低内存占用,示例如下 'user_id': 'int32', 'event_type': 'category', 'cost': 'float32' }, usecols=['user_id', 'event_type', 'cost']): # 只加载需要的列,不需要的列不读 # 这里写单块数据的处理逻辑,比如统计、过滤、存库等 processed_chunk = chunk[chunk['cost'] > 0] all_chunk_res.append(processed_chunk) # 若需要合并所有块的处理结果 final_df = pd.concat(all_chunk_res, ignore_index=True)
优化提示:
- 优先加
usecols参数,只加载业务需要的列,不必要的列直接跳过可以减少90%以上的内存占用 - 显式指定
dtype,默认pandas会给整数设为int64、浮点数设为float64、字符串设为object,按需换成更小的类型或者category分类类型可以大幅压缩内存 chunk_size可以灵活调整,内存大就设大一点,内存小就设小一点
方案2:使用Dask处理超大规模数据集
如果单块处理仍有内存压力,或者需要做全量的复杂计算(比如全局分组、join),可以用Dask库,它的接口和pandas几乎完全一致,会自动分块调度,支持处理远大于内存的数据集:
import dask.dataframe as dd # 直接读取zip包内的csv,无需手动解压 df = dd.read_csv( 'zip://Events_WE20200308.csv::Events_WE20200308.zip', dtype={ 'user_id': 'int32', 'event_type': 'category', 'cost': 'float32' }, usecols=['user_id', 'event_type', 'cost'] ) # 所有pandas的常用操作都支持,比如过滤、分组统计 res = df[df['cost'] > 0].groupby('event_type')['cost'].sum() # 最后调用compute触发计算,返回pandas的DataFrame/Series final_res = res.compute()
多zip批量处理
如果有多个zip文件,直接遍历所有zip文件路径,重复上述单文件的处理逻辑即可,无需一次性加载所有文件。
内容的提问来源于stack exchange,提问作者lala345
相关产品推荐
相关产品推荐

