Python MemoryError 未引发 - 而是调用 OOM-Killer?

Dav*_*ker 7 python linux memory out-of-memory

我有一个使用大量内存的 python 应用程序,当我在循环中处理它时应该没问题try / except MemoryError。不幸的是,MemoryError 异常从未引发 - 在此之前,python 被 OOM Killer 杀死(在 Debian Linux 上)。

问题是为什么......以及我如何在 Python 中捕获错误。如果我能抓住它,我有一个简单的缓解措施,但无一例外,我无法调用我的缓解措施。

有关信息,该应用程序正在处理视频,每帧大约是 15MB 的 numpy 对象。如果内存不足,我很乐意降低帧速率并重试。

我还尝试在加载每一帧时使用 psutil.available 跟踪内存使用情况,但该进程被终止,仍然有大约 350MB 显示为可用内存(总共 2GB)。我认为这是一个碎片问题。

因此我遇到的问题是我可以任意设置一些限制,例如,如果我获得 <500MB 的可用内存,然后以较低的帧速率重新开始,但这一切都感觉有点随意且不是很健壮。如果应用程序或者操作系统或硬件发生变化,我可能会发现下次它在剩余 501MB 时崩溃,或者其他什么......这就是为什么我宁愿通过 MemoryError 异常来处理它。

可悲的是,这似乎不是一个常见问题,“python 调用 oom-killer 异常”只给了我两页 Google 搜索结果!以前这里的大多数答案是“不要使用太多内存”,这不是很有帮助 - 在我的情况下,我想使用尽可能多的可用内存,但如果需要,我很乐意减少使用。只是 Python 没有给我机会在它被杀死之前这样做!

任何想法都非常感谢。

小智 0

numpy 倾向于将所有内容都放入内存中,因此您可以检查内存中可以同时容纳多少个视频文件。

“简单”测试可以加载到内存中的文件数量

import numpy as np
import sys
import math
import random


def real_size(obj):
    size_bytes = sys.getsizeof(obj)
    if size_bytes == 0:
        return "0B"
    size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
    i = int(math.floor(math.log(size_bytes, 1024)))
    p = math.pow(1024, i)
    s = round(size_bytes / p, 2)
    return "%s %s" % (s, size_name[i])


def object_15():
    """
    This creates an numpy object with ~15MB
    """
    row = [random.random()] * 2080000
    data = np.array(row).astype(float)
    return data


def my_read_file(number_of_files):
    data = object_15()
    for i in range(number_of_files):
        data = np.append(data, object_15())
    return data

print(f'Just checking that each object has ~15MB: {real_size(object_15())}')
number_of_files = 100
print(f'Objects loaded into memory = {number_of_files}\nTotal memory_used = {real_size(my_read_file(number_of_files))}')
Run Code Online (Sandbox Code Playgroud)

def object_15(): """ 这将创建一个约 15MB 的 numpy 对象 """ row = [random.random()] * 2080000 data = np.array(row).astype(float) 返回数据

def my_read_file(number_of_files): data = object_15() for i in range(number_of_files): data = np.append(data, object_15()) 返回数据

print(f'仅检查每个对象是否有 ~15MB: {real_size(object_15())}') number_of_files = 100 print(f'加载到内存中的对象 = {number_of_files}\n总内存使用 = {real_size(my_read_file(number_of_files)) }')

根据此测试,您应该能够拥有约 100 个 numpy 对象,每个对象大小约 15MB,并且使用的空间不超过 2 GB。请调整代码并尝试满足您的特定需求/对象类型。

更多信息请点击这里:

您可能需要考虑的其他主题是: