Python2中函数传参与函数内加载大数据集的内存消耗对比及优化
Python2下Pandas大型数据集内存优化方案
一、函数内加载数据集的内存优势
先对比你给出的两种写法:
第一种写法:
def func(df): # 处理逻辑 return result df = pd.read_csv(path_to_data) func(df)
第二种写法:
def func(path_to_data): df = pd.read_csv(path_to_data) # 处理逻辑 return result func(path_to_data)
两者的内存差异在于:
- Python里函数传参是引用传递,第一种写法中,函数内的
df和全局的df指向同一个DataFrame对象,不会额外复制内存。但函数执行完后,全局的df还会留在内存里,除非你手动删除或者等垃圾回收触发。 - 第二种写法里,
df是函数的局部变量,只要返回的result不依赖df,函数执行完毕后df会立刻被标记为可回收,内存释放更快。如果你的流程不需要在函数外部保留原始数据集,这种写法确实能缩短内存占用的时间,降低内存溢出的风险。
注意:如果函数内对df做了原地修改(比如加inplace=True的操作),两种写法都会影响原对象,但这属于逻辑副作用,和内存优化无关。
二、Python2 + Pandas内存优化技巧
1. 读取阶段直接控内存
- 指定数据类型:Pandas默认自动推断类型,但很多时候可以用更小的类型存储,比如把
int64改成int32/int16(数值范围允许的话),float64改成float32,重复值多的字符串列用category类型:
dtype_config = { "user_id": "int32", "order_status": "category", "price": "float32" } df = pd.read_csv(path_to_data, dtype=dtype_config)
- 只加载需要的列:用
usecols参数指定要读取的列,避免加载无关数据:
df = pd.read_csv(path_to_data, usecols=["user_id", "price", "create_time"])
- 分块读取:用
chunksize参数拆分数据集,分批处理,不用一次性加载全部数据:
chunk_iterator = pd.read_csv(path_to_data, chunksize=10000) for chunk in chunk_iterator: # 处理单块数据逻辑 process_single_chunk(chunk)
- 关闭默认索引:如果不需要自动生成的整数索引,加
index_col=False,节省内存:
df = pd.read_csv(path_to_data, index_col=False)
2. 主动清理内存
- 手动删除无用变量:用
del删掉不用的变量,再调用gc.collect()强制触发垃圾回收(Python2需要先导入gc模块):
import gc # 数据处理完成后 del df gc.collect()
- 避免不必要的副本:尽量用原地操作(比如
df.drop(columns=["unused_col"], inplace=True)),减少Pandas隐式创建的副本;如果必须复制,用.copy()明确声明,避免链式操作导致的内存浪费。 - 多用局部变量:局部变量的回收速度比全局变量快,尽量把数据处理逻辑封装在函数里,变量作为局部变量存在。
3. 优化数据结构
- 用
category存重复字符串:当字符串列的重复率超过50%时,转成category类型能大幅减少内存占用:
df["product_type"] = df["product_type"].astype("category")
- 稀疏数据用稀疏结构:对于大部分值为NaN的列,使用
SparseSeries或SparseDataFrame(Pandas 0.19+版本支持):
from pandas import SparseSeries sparse_col = SparseSeries(df["mostly_nan_col"], fill_value=np.nan)
- 拒绝嵌套结构:不要在DataFrame里存列表、字典这类嵌套对象,不仅占内存,处理效率还低。
4. Python2专属优化点
- 别用
__del__方法:Python2里带__del__的对象会延迟垃圾回收,尽量不要自定义带这个方法的类。 - 循环用
xrange代替range:xrange生成的是迭代器,不会一次性生成所有元素,节省内存。 - 少用全局变量:全局变量会长期占用内存,尽量把逻辑封装成函数,变量放在局部作用域里。
内容的提问来源于stack exchange,提问作者Roger V.
相关产品推荐
相关产品推荐

