长时间运行的 Python 程序(使用 Pandas)不断增加内存使用量
Posted
技术标签:
【中文标题】长时间运行的 Python 程序(使用 Pandas)不断增加内存使用量【英文标题】:Long-running Python program (using Pandas) keeps ramping up memory usage 【发布时间】:2019-12-18 11:02:39 【问题描述】:我正在运行一个 python 脚本,该脚本在无限循环中使用 Pandas 函数处理和处理数据。但随着时间的推移,该程序似乎正在泄漏内存。
这是由 memory-profiler 包生成的图表:
遗憾的是,我无法确定内存使用量增加的原因。据我所知,所有数据(pandas 时间序列)都存储在对象Obj
中,我使用pandas 函数.memory_usage
和objsize 函数get_deep_size()
跟踪该对象的内存使用情况。根据他们的输出,内存使用量应该稳定在 90-100 MB 左右。除此之外,我看不出内存可以在哪里增加。
知道 python 程序在 docker 容器中运行可能很有用。
下面是脚本的简化版本,它应该阐明基本的工作原理。
from datetime import datetime
from time import sleep
import objsize
from dateutil import relativedelta
def update_data(Obj, now_utctime):
# attaining the newest timeseries data
new_data = requests.get(host, start=Obj.data[0].index, end=now_utctime)
Obj.data.append(new_data)
# cut off data older than 1 day
Obj.data.truncate(before=now_utctime-relativedelta.relativedelta(days=1))
class ExampleClass():
def __init__(self):
now_utctime = datetime.utcnow()
data = requests.get(host, start=now_utctime-relativedelta.relativedelta(days=1), end=now_utctime)
Obj = ExampleClass()
while True:
update_data(Obj, datetime.utcnow())
logger.info(f"Average at datetime.utcnow() is at Obj.data.mean()")
logger.info(f"Stored timeseries memory usage at Obj.data.memory_usage(deep=True)* 10 ** -6 MB")
logger.info(f"Stored Object memory usage at objsize.get_deep_size(Obj) * 10 ** -6 MB")
time.sleep(60)
任何关于内存可以增加的地方或如何进一步调查的建议,我们将不胜感激。
编辑:查看图表,在我截断之前会有峰值是有道理的,但由于数据入口是稳定的,我不知道为什么它不会正常化,但仍然存在在更高的点。然后每第 4 个周期后就会出现这种突然下降,即使该过程没有另一个更广泛的周期可以解释这一点……
【问题讨论】:
看来Obj.data
应该是某种列表,而不是requests.Response
对象,对吧?
请求调用返回一个熊猫系列
那么问题可能与 pandas 内存泄漏有关,您最好在帖子和标签中突出显示这一点。相反,您可能应该将 docker 排除在外,除非您只能在通过 docker 运行时重现该问题。
相关:***.com/q/14224068/1025391
这意味着问题绝对是python脚本的一部分,与docker没有任何关系?
【参考方案1】:
正如 moooeeeeep 所建议的,内存使用量的增加与内存泄漏有关,其确切来源仍有待确定。但是,我能够通过在每个循环后通过gc.collect()
手动调用垃圾收集器来解决此问题。
【讨论】:
可能与here 和here 描述的问题相同(熊猫以某种方式泄漏内存)。以上是关于长时间运行的 Python 程序(使用 Pandas)不断增加内存使用量的主要内容,如果未能解决你的问题,请参考以下文章
Python & Tkinter -> 关于调用冻结程序的长时间运行函数
以与长时间运行的 Python 进程不同的用户身份运行子进程