我有一个程序,会像下面这样反复循环遍历一个pandas数据帧:
monts = [some months]
for month in months:
df = original_df[original_df.month == month].copy()
result = some_function(df)
print(result)
然而,每次迭代所需的内存仍在增加。
types | # objects | total size
================================================ | =========== | ============
<class 'pandas.core.frame.DataFrame | 22 | 6.54 GB
<class 'pandas.core.series.Series | 1198 | 4.72 GB
<class 'numpy.ndarray | 1707 | 648.19 MB
<class 'pandas.core.categorical.Categorical | 238 | 368.90 MB
<class 'pandas.core.indexes.base.Index | 256 | 312.03 MB
================================================ | =========== | ============
<class 'pandas.core.frame.DataFrame | 30 | 9.04 GB
<class 'pandas.core.series.Series | 2262 | 7.29 GB
<class 'numpy.ndarray | 2958 | 834.49 MB
<class 'pandas.core.categorical.Categorical | 356 | 569.39 MB
<class 'pandas.core.indexes.base.Index | 380 | 481.21 MB
你有没有一些关于如何找到内存泄漏的建议?
编辑
注意,每次迭代手动调用 gc.collect()
并不能帮助解决问题。
编辑2
这里提供了一个最小化的示例:
import pandas as pd
from numpy.random import randn
df = pd.DataFrame(randn(10000,3),columns=list('ABC'))
for i in range(10):
print(i)
something = df.copy()
print('#########################')
print('trying to limit memory pressure')
from pympler import muppy, summary
all_objects = muppy.get_objects()
sum1 = summary.summarize(all_objects)
summary.print_(sum1)
print('#########################')
如您所见,这表明内存消耗正在增加。一开始使用9MB,在10次迭代后已经使用了30MB。
编辑3
实际上,@Steven的评论可能有一定道理。
for i in range(10):
something = df.copy()
foo_thing = summary.summarize(muppy.get_objects())
summary.print_(foo_thing)
正在显示问题,然而
for i in range(10):
something = df.copy()
summary.print_(summary.summarize(muppy.get_objects()))
一切正常。我该如何找到所有导致问题的变量?我认为这尤其重要,因为在我的实际代码中,其中一些是相当大的pandas.Dataframes。
编辑4
手动添加foo_thing = None
后,另一个脚本也能正常工作。问题在于 - 如何高效地找到所有这样的情况。Python不应该自动识别不再使用的变量吗?
编辑5
当引入像下面这样的函数时:
def do_some_stuff():
foo_thing = summary.summarize(muppy.get_objects())
summary.print_(foo_thing)
for i in range(10):
something = df.copy()
do_some_stuff()
内存泄漏问题似乎已经得到了解决。
编辑6
实际上,内存泄漏问题并没有得到解决。好的一面是,summary
现在不再报告内存消耗急剧增长的情况。不好的一面是:任务管理器/活动监视器告诉我事实并非如此 - 而且Python程序最终会崩溃。
some_function(df)
是否具有创建对df
的持久引用或以其他方式泄漏的副作用? - Steven Rumbalski