【问题标题】:Memory leak when reading value from a Pandas Dataframe从 Pandas Dataframe 读取值时发生内存泄漏
【发布时间】:2017-02-01 21:05:28
【问题描述】:

当反复从数据帧复制一个值时,pandas 似乎触发了内存泄漏。

在每次迭代开始时,通过从初始数据帧复制来创建数据帧。通过从当前数据框中复制单个值来创建第二个变量。

在每次迭代结束时,删除这两个变量,并打印当前进程使用的内存(每 1000 次迭代)。 used memory increases

我认为在某些时候可能会有一些隐式副本(可能在读取数据帧值时)。

快速解决此问题会导致在每次迭代中应用垃圾收集器,但这是一个相当昂贵的解决方案:该过程至少慢 10 倍。

有没有明确解释为什么会出现这个问题?

import os, gc
import psutil, pandas as pd

N_ITER = 100000
DF_SIZE = 10000

# Define the DataFrame
df = pd.DataFrame(index=range(DF_SIZE), columns=['my_col'])
df['my_col'] = range(DF_SIZE)


def memory_usage():
    """Return the memory usage of the current python process."""
    return psutil.Process(os.getpid()).memory_info().rss / 1024 ** 2


if __name__ == '__main__':

    for i in range(N_ITER):
        df_ind = pd.DataFrame(df.copy())
        val = df_ind.at[4242, 'my_col']  # The line that provokes the leak!

        del df_ind, val  # Useless
        # gc.collect()  # Garbage Collector prevents the leak but is slow

        if (i % 1000) == 0:
            print('Iter {}\t {} MB'.format(i, int(memory_usage())))

【问题讨论】:

  • 如果调用gc.collect() 释放内存,那么这是完全正常的预期行为。某处有一些循环引用阻止引用计数机制释放内存。让你的程序运行;如果太多未声明的、可声明的对象堆积起来,GC 会自动运行并清理它们。
  • 感谢您的回答。我让代码运行,然后等着看。那么你将如何防止这些循环引用呢?
  • 这必须在 Pandas 实现中完成。

标签: python pandas memory-leaks


【解决方案1】:

好吧,看来真正的痛苦来自df_ind 的创建方式。

对原始数据框df 使用引用 似乎可行,但如果我们打算修改̀df_ind 可能会有点冒险。

使用原始数据帧df副本 会触发内存泄漏。可能有来自df 的无用元素的一些隐式副本。这些复制的元素不被del捕获,但被gc.collect()捕获。这会带来时间成本,因为此操作需要时间。

这里列出了解决此内存泄漏的不同尝试及其结果:

df_ind = df                    # Works! Dangerous since df could be modified

df_ind = copy.copy(df)         # Works! Equivalent to df_ind = df
df_ind = df.copy.deepcopy(df)  # Fails.

df_ind = df.copy(deep=False)   # Works! Equivalent to df_ind = df
df_ind = df.copy(deep=True)    # Fails.

总结一下:

  • 如果您想要修改临时数据帧,那么不要使用 pandas。您可以使用字典或压缩列表来获得所需的内容。

  • 如果您不想修改临时数据帧,则使用 pandas 和显式选项 df_ind = df.copy(deep=False)

【讨论】:

    猜你喜欢
    • 2023-01-23
    • 2012-11-19
    • 2014-05-04
    • 2020-12-04
    • 2014-12-11
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多