Python使用Pandas循环追加数据存储Feather出现内存泄漏如何解决?
问题解决方案
一、保留Pandas使用逻辑的修复方法
你遇到的内存问题核心不是Pandas本身的内存泄漏,是DataFrame.append()方法的错误使用导致的:该方法在Pandas 2.0+已经正式弃用,每次调用都会生成一个全新的DataFrame对象,产生大量无法被及时回收的中间临时副本,加上每次传字典插入时Pandas需要反复做字段类型推断,进一步加剧内存占用。
修复步骤如下:
- 放弃逐行append到DataFrame的逻辑,改为先把每行数据存入普通Python列表,攒到需要落盘的时机再一次性转DataFrame:
import pandas import datetime import gc tmp_rows = [] # 用列表存字典,完全没有中间DF开销 while measure: do_something() # 直接把行数据追加到列表,无任何Pandas开销 tmp_rows.append({'var1':var1,'var2':var2,...,'varN':varN}) if save_data_in_this_iteration(): # 一次性转DF,仅生成一次DF对象 temporary_df = pandas.DataFrame(tmp_rows) # 提前指定dtype可以进一步减少开销,示例: # temporary_df = pandas.DataFrame(tmp_rows, dtype={"var1": int, "var2": float...}) temporary_df.to_feather(f'file_{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}.fd') # 手动释放变量后触发垃圾回收 del temporary_df gc.collect() # 清空列表即可 tmp_rows.clear() merge_all_feathers_into_single_feather()
- 如果你坚持要逐行操作DataFrame,可以提前初始化固定结构、固定dtype的空DataFrame,再用
loc索引赋值,避免每次生成新DF:
# 提前定义所有字段和对应类型 cols = ["var1", "var2", ..., "varN"] dtypes = [int, float, ..., str] temporary_df = pandas.DataFrame(columns=cols).astype(dict(zip(cols, dtypes))) while measure: do_something() temporary_df.loc[len(temporary_df)] = [var1, var2, ..., varN] if save_data_in_this_iteration(): temporary_df.to_feather(f'file_{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}.fd') temporary_df.drop(temporary_df.index, inplace=True) gc.collect()
二、不用Pandas的替代方案
方案1:标准库csv.DictWriter+列式存储组合(改造成本最低)
同时解决你提到的两个痛点:
- 日常采集时用
csv.DictWriter写入临时CSV,不需要手动拼接字符串,直接传字典即可,完全避免字段顺序错误、漏写的问题 - 攒批后直接用pyarrow把CSV转成feather/parquet格式,自动保留所有数据类型,全程不需要引入Pandas
方案2:用Polars替代Pandas
Polars是内存优化的数据分析库,接口和Pandas高度兼容,没有Pandas的append内存问题,性能是Pandas的3-10倍,内存占用仅为Pandas的1/3左右,你只需要把导入语句换成import polars as pl,调整少量API即可直接复用现有逻辑。
方案3:用SQLite存储
直接把采集到的数据写入本地SQLite数据库,原生支持所有常见数据类型,不需要攒批,写入即持久化,完全不存在内存持续上涨的问题,后续合并、查询数据都比处理多个feather文件更灵活。
内容的提问来源于stack exchange,提问作者user171780
相关产品推荐
相关产品推荐

