【问题标题】:MemoryError hook in Python?Python中的MemoryError钩子?
【发布时间】:2011-04-28 19:43:39
【问题描述】:

有没有办法全局捕获 MemoryError 异常,以便库可以清除缓存,而不是让用户代码看到 MemoryError?

我正在用 Python 开发一个内存缓存库,用于存储非常大的对象,以至于用户通常希望使用所有可用的 RAM 来简化他们的脚本和/或加快它们的速度。我希望能够有一个钩子,python 解释器要求回调函数释放一些 RAM,以避免在用户代码中调用 MemoryError。

操作系统:Solaris 和/或 Linux

Python:cPython 2.6.*


编辑:我正在寻找一种不会被 except 块处理的机制。如果由于任何原因在任何代码中都会出现内存错误,我希望 Python 解释器首先尝试使用回调来释放一些 RAM,并且永远不会生成 MemoryError 异常。我不控制会产生错误的代码,我希望我的缓存能够积极地使用尽可能多的 RAM,根据用户代码的需要自动释放 RAM。

【问题讨论】:

    标签: python memory-management caching


    【解决方案1】:

    这不是处理内存管理的好方法。当您看到 MemoryError 时,您已经处于临界状态,内核可能接近于杀死进程以释放内存,并且在许多系统上您永远不会看到它,因为它会去交换或只是 OOM-杀死你的进程而不是分配失败。

    您可能会看到 MemoryError 的唯一可恢复情况是在尝试进行不适合可用地址空间的非常大的分配之后,仅在 32 位系统上常见。

    如果你想要一个缓存来根据需要释放内存用于其他分配,它不需要与 errors 接口,而是与分配器本身接口。这样,当您需要为分配释放内存时,您就会知道需要多少连续内存,否则您会盲目猜测。这还意味着您可以在内存分配发生时跟踪它们,这样您就可以将内存使用量保持在特定水平,而不是让它不受限制地增长,然后在它变得过高时尝试恢复。

    我强烈建议,对于大多数应用程序来说,这种缓存行为过于复杂,但通常最好只使用一定数量的内存进行缓存。

    【讨论】:

      【解决方案2】:

      MemoryError 是一个异常,您应该能够在 except 块中捕获它。

      【讨论】:

      • 我试图澄清这个问题。我希望我的库在任何代码中拦截 MemoryError 的创建,并且该代码不会有任何尝试...除了其中的块。
      【解决方案3】:

      我希望我能对 Glenn 的回答发表评论……尽管我同意反对使用 MemoryException 作为处理缓存大小的一种方式的总体想法,但这并不一定意味着当你捕获它们时你的系统就是我们的重击。有些人在没有交换的情况下运行,你也可以在使用 ulimit 限制最大进程大小时得到它们。此外,当使用软限制时,您甚至可以提高软限制以优雅地处理您在内存耗尽时处理自己的死亡(假设有一种方法可以在不分配更多内存的情况下提高它;我还没有尝试过)。

      捕获未捕获的异常意味着出现问题,而您不知道是什么。这意味着您的应用程序可能会开始以意想不到的方式运行,就像您开始删除随机代码行一样!我在某些应用程序中使用了通用异常处理程序,但只是为了向用户显示一条好消息(特别是对 GUI 有用)然后消失。

      您可以像这样挂钩您的异常处理程序:

      sys.excepthook = <your_exceptionhook>
      

      参数是异常类、异常实例和回溯对象。您可以将这些参数以相同的顺序传递给 traceback.format_exception() 以生成 python 在未捕获异常时写入 stderr 的回溯消息。

      注意:我没有尝试过它是否对 MemoryException 错误有用,但这是您捕获未捕获异常的方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-20
        • 1970-01-01
        • 1970-01-01
        • 2018-06-13
        • 1970-01-01
        • 1970-01-01
        • 2011-12-09
        • 2013-12-21
        相关资源
        最近更新 更多