我有一个长时间运行的脚本,如果让它运行足够长的时间,它将占用系统上的所有内存。
在不讨论剧本细节的情况下,我有两个问题:
是否有任何“最佳实践”可以遵循,这将有助于防止泄漏的发生? 在Python中有哪些调试内存泄漏的技术?
我有一个长时间运行的脚本,如果让它运行足够长的时间,它将占用系统上的所有内存。
在不讨论剧本细节的情况下,我有两个问题:
是否有任何“最佳实践”可以遵循,这将有助于防止泄漏的发生? 在Python中有哪些调试内存泄漏的技术?
查看这篇文章:跟踪python内存泄漏
另外,请注意,垃圾收集模块实际上可以设置调试标志。看看set_debug函数。另外,查看Gnibbler编写的代码,以确定调用后创建的对象类型。
不确定python中内存泄漏的“最佳实践”,但python应该通过它的垃圾收集器清除自己的内存。所以我主要会从检查一些短的循环列表开始,因为它们不会被垃圾收集器拾取。
您应该特别查看全局数据或静态数据(长寿数据)。
当这些数据不受限制地增长时,在Python中也会遇到麻烦。
垃圾收集器只能收集不再被引用的数据。但是静态数据可以连接应该释放的数据元素。
另一个问题可能是内存周期,但至少在理论上垃圾收集器应该找到并消除周期——至少只要它们不依赖于一些长期存在的数据。
什么样的长寿命数据特别麻烦?仔细查看任何列表和字典——它们可以无限制地增长。在字典中,你甚至可能看不到这个问题,因为当你访问字典时,字典中的键数可能对你来说不是很明显……
我尝试了前面提到的大多数选项,但发现这个小而直观的包是最好的: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的文档,特别是识别内存泄漏一节。
至于最佳实践,请密切关注递归函数。在我的例子中,我遇到了递归的问题(在不需要的地方)。举个简单的例子:
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()
Tracemalloc模块从Python 3.4开始作为内置模块集成,显然,它也可以作为第三方库用于先前版本的Python(不过还没有测试它)。
这个模块能够输出分配最多内存的精确文件和行。恕我直言,这个信息比为每种类型分配的实例数量(99%的情况下最终会有很多元组,这是一个线索,但在大多数情况下几乎没有帮助)有价值得多。
我建议你将tracemalloc与吡拉西矿联合使用。十有八九,在pyrasite-shell中运行前10个代码片段将为您提供足够的信息和提示,以在10分钟内修复泄漏。然而,如果您仍然无法找到泄漏原因,pyrasite-shell结合本文中提到的其他工具可能也会给您更多的提示。您还应该看看pyrasite提供的所有额外帮助(例如内存查看器)。