Python内存泄漏[关闭]

Posted

技术标签:

【中文标题】Python内存泄漏[关闭]【英文标题】:Python memory leaks [closed] 【发布时间】:2010-11-28 22:57:04 【问题描述】:

我有一个长时间运行的脚本,如果让它运行足够长的时间,它将消耗我系统上的所有内存。

在不详细介绍脚本的情况下,我有两个问题:

    是否有任何“最佳实践”可以遵循,这将有助于防止发生泄漏? 有哪些技术可以在 Python 中调试内存泄漏?

【问题讨论】:

我发现this recipe 很有帮助。 打印出来的数据似乎太多,没用 @Casebash:如果该函数打印出任何内容,那么您就大错特错了。它列出了具有__del__ 方法的对象,这些对象除了循环之外不再被引用。由于__del__ 的问题,无法打破循环。修复它! How do I profile memory usage in Python?的可能重复 【参考方案1】:

看看这篇文章:Tracing python memory leaks

另外,请注意garbage collection module 实际上可以设置调试标志。查看set_debug 函数。此外,查看this code by Gnibbler 以确定调用后创建的对象类型。

【讨论】:

【参考方案2】:

不确定python中内存泄漏的“最佳实践”,但python应该通过它的垃圾收集器清除它自己的内存。所以主要是我会首先检查一些短的循环列表,因为它们不会被垃圾收集器拾取。

【讨论】:

或对永久保存的对象的引用等 你们能否提供循环列表和永久保存的对象的示例?【参考方案3】:

您应该特别查看一下您的全局或静态数据(长期存在的数据)。

当这些数据不受限制地增长时,你也可以在 Python 中遇到麻烦。

垃圾收集器只能收集不再被引用的数据。但是你的静态数据可以连接应该被释放的数据元素。

另一个问题可能是内存周期,但至少在理论上垃圾收集器应该找到并消除周期 - 至少只要它们没有被一些长期存在的数据所吸引。

什么样的长寿命数据特别麻烦?仔细查看任何列表和字典——它们可以无限制地增长。在字典中,您甚至可能看不到问题的出现,因为当您访问 dicts 时,字典中的键数可能对您来说不太明显......

【讨论】:

【参考方案4】:

这绝不是详尽的建议。但是,在编写时要记住避免未来内存泄漏(循环)的第一件事是确保任何接受回调引用的东西都应该将该回调存储为弱引用。

【讨论】:

你将如何在 python 中做到这一点? 为什么我们应该将回调存储为弱引用?回调有什么特别之处?【参考方案5】:

让我推荐我创建的mem_top 工具

它帮助我解决了类似的问题

它只是立即显示 Python 程序中内存泄漏的主要嫌疑人

【讨论】:

确实如此......但它在使用/结果解释方面提供的很少 @me_ ,此工具同时记录了“使用”和“解释结果”部分。我是否应该添加解释,例如“refs 是来自对象的引用计数,types 是这种类型的对象的计数,bytes 是对象的大小” - 记录这一点不是太明显了吗? 该工具的使用文档只写了一行“不时:logging.debug(mem_top())”,而它对结果的解释是作者在没有上下文的情况下真实生活中的错误跟踪经验。 .这不是一个技术规范,可以准确地告诉开发人员他们在看什么...我不是在敲你的答案...它显示高级嫌疑人已计费...它没有提供足够的文档来完全理解使用结果...例如,在“解释结果”输出中,为什么“GearmanJobRequest”显然是个问题?没有解释为什么... 我想我无意中敲了你的工具,你是作者......无意冒犯...... @me_ ,我刚刚在“使用”中添加了下一步,添加了“计数器”部分,添加了解释为什么 Gearman 在现实生活中是一个嫌疑犯,记录了“ mem_top()”,并将其全部上传为 v0.1.7 - 请查看是否还有其他改进。谢谢! )【参考方案6】:

我尝试了前面提到的大多数选项,但发现这个小巧直观的包是最好的:pympler

跟踪未被垃圾回收的对象非常简单,请查看以下小示例:

通过pip install pympler安装包

from pympler.tracker import SummaryTracker
tracker = SummaryTracker()

# ... some code you want to investigate ...

tracker.print_diff()

输出显示所有已添加的对象,以及它们消耗的内存。

样本输出:

                                 types |   # objects |   total size
====================================== | =========== | ============
                                  list |        1095 |    160.78 KB
                                   str |        1093 |     66.33 KB
                                   int |         120 |      2.81 KB
                                  dict |           3 |       840 B
      frame (codename: create_summary) |           1 |       560 B
          frame (codename: print_diff) |           1 |       480 B

此软件包提供了更多功能。检查pympler's documentation,特别是Identifying memory leaks部分。

【讨论】:

值得注意的是pympler可以是SLOW。如果您正在做一些半实时的事情,它会完全削弱您的应用程序性能。 @sebpiq 奇怪的是,我也遇到了同样的情况……你知道为什么会发生这种情况吗?快速浏览一下源代码并没有真正的洞察力。【参考方案7】:

就最佳实践而言,请留意递归函数。就我而言,我遇到了递归问题(不需要)。我正在做的一个简化示例:

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    if my_flag:  # restart the function if a certain flag is true
        my_function()

def main():
    my_function()

以这种递归方式操作不会触发垃圾收集并清除函数的剩余部分,因此每次通过内存使用量都在增长。

我的解决方案是从 my_function() 中提取递归调用,并让 main() 处理何时再次调用它。这样函数自然结束并自行清理。

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    .....
    return my_flag

def main():
    result = my_function()
    if result:
        my_function()

【讨论】:

如果达到递归深度限制,以这种方式使用递归也会中断,因为 Python 不会优化尾调用。默认情况下,这是 1000 次递归调用。【参考方案8】:

检测和定位长时间运行的进程的内存泄漏,例如在生产环境中,您现在可以使用stackimpact。它在下面使用tracemalloc。更多信息在this post。

【讨论】:

【参考方案9】:

Tracemalloc module 从 Python 3.4 开始作为内置模块集成,并且显然它也可用于以前版本的 Python 为 a third-party library(虽然尚未测试)。

此模块能够输出分配最多内存的精确文件和行。恕我直言,此信息比为每种类型分配的实例数更有价值(最终在 99% 的情况下是很多元组,这是一个线索,但在大多数情况下几乎没有帮助)。

我建议您将 tracemalloc 与 pyrasite 结合使用。 10 次中有 9 次在 pyrasite-shell 中运行 top 10 snippet 将为您提供足够的信息和提示,以便在 10 分钟内修复泄漏。但是,如果您仍然无法找到泄漏原因,那么 pyrasite-shell 与此线程中提到的其他工具相结合可能也会为您提供更多提示。您还应该查看 pyrasite 提供的所有额外帮助程序(例如内存查看器)。

【讨论】:

pytracemalloc.readthedocs.io 不存在了

以上是关于Python内存泄漏[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

user32 和内存泄漏? [关闭]

解释 DrMemory 日志,内存泄漏 [关闭]

线程关闭期间Win64 Delphi RTL中的内存泄漏?

Tensorflow:即使在关闭会话时内存泄漏?

javascript中的关闭和回调内存泄漏

Google App Engine / Datastore / Flask / Python app 中的内存泄漏