在Python 3中取消勾选pandas/numpy时内存泄漏

2024-10-05 13:16:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我遇到内存泄漏,调试时遇到问题。第一部分描述在运行时生成样本数据时发生的情况,第二部分描述在将样本数据缓存到文件中时发生的情况

1)当我取消拾取pandas(版本1.0)dataframes的集合(在本例中为adict)时,在函数内我会遇到内存泄漏。即使在调用gc.collect()之后,内存使用量也从开始时的131MB增加到结束时的2075 MB(请参见屏幕截图中的第一行和最后一行)。代码如下所示。屏幕截图还显示了tracemalloc的输出

enter image description here

因为这是在一个函数中运行的,所以我希望所有的局部变量在返回时都会被清除。有趣的是,当在函数中输入del数据时,在函数中生成样本数据的情况下,问题就消失了

enter image description here

def print_process_mem_usage(do_print=True):
    import os
    import psutil
    process = psutil.Process(os.getpid())
    mem_usg = process.memory_info().rss/1.e6
    if do_print:
        print(f'{mem_usg:3,.0f} MB')
    else:
        return mem_usg


def func():
    import pandas as pd
    import pickle
    df = pd.DataFrame(pd.util.testing.getTimeSeriesData(nper=60_000))
    data = {ix: df.copy() for ix in range(1000)}
    stream = pickle.dumps(data)
    # del data

    print_process_mem_usage()
    out = pickle.loads(stream)
    return out

def trace_memory(func):
    import tracemalloc
    import gc
    tracemalloc.start()
    print_process_mem_usage()
    out = func()
    snapshot1 = tracemalloc.take_snapshot()
    del out
    print_process_mem_usage()
    snapshot2 = tracemalloc.take_snapshot()
    tracemalloc.stop()
    gc.collect()
    print('snapshot 1')
    for stat in snapshot1.statistics('lineno')[:10]:
        print(stat)
    print('snapshot 2')
    for stat in snapshot2.statistics('lineno')[:10]:
        print(stat)
    print_process_mem_usage()

2)更糟糕的是,当我将数据写入文件时,就像这样

def write_sample_data_to_file():
    with open('/tmp/output1', 'wb') as f:
        import pickle
        import numpy as np
        import pandas as pd
        df = pd.DataFrame(pd.util.testing.getTimeSeriesData(nper=60_000))
        stream = {ix: df.copy() for ix in range(1000)}
        stream = pickle.dumps(stream)
        f.write(stream)

write_sample_data_to_file()

然后在以下加载程序函数上调用trace_memory:

def func():
    with open('/tmp/output1', 'rb') as f:
        stream = f.read()

    print_process_mem_usage()
    import pickle
    out = pickle.loads(stream)
    del stream

    return out

即使我在这个函数中删除stream,内存也不会可靠地释放。反复调用函数(有时还需要重新启动内核)最终会再次引发问题(大约2GB额外内存使用)

有什么想法正在发生什么或者如何进一步追踪这个问题吗


Tags: 数据函数内存importstreamdefasusage

热门问题