首页 文章

Python内存泄漏

提问于
浏览
127

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

没有详细介绍脚本,我有两个问题:

  • 是否有"Best Practices"跟随,这将有助于防止泄漏发生?

  • 有哪些技术可以调试Python中的内存泄漏?

9 回答

  • 3

    看看这篇文章:Tracing python memory leaks

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

  • 66

    我尝试了之前提到的大多数选项,但发现这个小而直观的包是最好的: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部分 .

  • 5

    让我推荐mem_top工具,
    这帮我解决了类似的问题 .

    它只是立即显示Python程序中内存泄漏的最大嫌疑人 .

  • 7

    您应该专门查看全局或静态数据(长寿命数据) .

    当这些数据不受限制地增长时,您也可能在Python中遇到麻烦 .

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

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

    什么样的长寿数据特别麻烦?仔细查看任何列表和词典 - 它们可以不受限制地增长 . 在字典中,您甚至可能看不到麻烦,因为当您访问dicts时,字典中的键数可能对您来说不是很大的可见性......

  • 82

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

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

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

  • 3

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

    enter image description here

  • 11

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

  • 20

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

  • 4

    就最佳实践而言,请密切关注递归函数 . 在我的情况下,我遇到了递归问题(没有必要) . 我正在做的一个简化示例:

    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()
    

相关问题