Хук MemoryError в Python? - PullRequest
       10

Хук MemoryError в Python?

4 голосов
/ 21 октября 2010

Есть ли способ глобально перехватывать исключения MemoryError, чтобы библиотека могла очищать кеши вместо того, чтобы позволить MemoryError быть видимым кодом пользователя?

Я разрабатываю библиотеку кэширования памяти на Python, которая хранит очень большие объекты, и пользователи часто хотят использовать всю доступную оперативную память для упрощения своих сценариев и / или ускорения их. Я хотел бы иметь возможность ловить, когда интерпретатор python запрашивает функцию обратного вызова для освобождения некоторой оперативной памяти, чтобы избежать вызова MemoryError в пользовательском коде.

ОС: Solaris и / или Linux

Python: cPython 2.6. *


РЕДАКТИРОВАТЬ: Я ищу механизм, который не будет обрабатываться блоком исключений. Если по какой-либо причине в каком-либо коде будет ошибка памяти, я бы хотел, чтобы интерпретатор Python сначала попытался использовать обратный вызов для освобождения некоторой оперативной памяти и никогда не генерировал исключение MemoryError. Я не контролирую код, который будет генерировать ошибки, и я хотел бы, чтобы мой кэш мог агрессивно использовать столько ОЗУ, сколько ему нужно, автоматически освобождая ОЗУ, как того требует код пользователя.

Ответы [ 3 ]

4 голосов
/ 22 октября 2010

Это не очень хороший способ управления памятью. К тому времени, когда вы видите MemoryError, вы уже находитесь в критическом состоянии, когда ядро, вероятно, близко к уничтожению процессов, чтобы освободить память, и во многих системах вы никогда не увидите его, потому что оно пойдет на подкачку или просто OOM убить ваш процесс, а не сбой распределения.

Единственный восстанавливаемый случай, который вы можете увидеть в MemoryError, - это попытка выполнить очень большое выделение, которое не помещается в доступное адресное пространство, только для 32-битных систем.

Если вы хотите иметь кеш, который освобождает память, необходимую для других распределений, он должен взаимодействовать не с ошибками , а с самим распределителем. Таким образом, когда вам нужно освободить память для выделения, вы будете знать , сколько нужно непрерывной памяти, иначе вы будете угадывать вслепую. Это также означает, что вы можете отслеживать распределение памяти по мере того, как оно происходит, поэтому вы можете сохранить использование памяти на определенном уровне, не позволяя ей расти беспрепятственно, а затем пытаясь восстановить, когда она становится слишком высокой.

Я бы настоятельно предположил, что для большинства приложений этот вид кэширования слишком сложен - вам, как правило, лучше просто использовать установленный объем памяти для кэша.

1 голос
/ 25 августа 2013

Хотел бы я прокомментировать ответ Гленна ... хотя я согласен с общей идеей против использования MemoryException в качестве способа обработки размера кэша, это не обязательно означает, что ваша система не в порядке, когда вы их ловите.Некоторые люди работают без подкачки, и вы также можете получить их, используя ulimit для ограничения максимального размера процесса.Кроме того, при использовании мягких ограничений вы можете даже увеличить мягкий предел, чтобы корректно обрабатывать собственную смерть при исчерпании памяти (при условии, что есть способ повысить ее без выделения дополнительной памяти; я еще никогда не пробовал).

Поймать неисследованное исключение означает, что что-то пошло не так, и вы не знаете что.Это означает, что ваше приложение может начать вести себя неожиданным образом, как если бы вы начали удалять случайные строки кодов!Я использовал универсальный обработчик исключений в некоторых приложениях, но только для отображения приятного сообщения пользователю (особенно полезно с графическим интерфейсом) и отмирание.

Вы можете подключить свой обработчик исключений так:

sys.excepthook = <your_exceptionhook>

Параметры - это класс исключения, экземпляр исключения и объект трассировки.Вы можете передать эти параметры в том же порядке в traceback.format_exception (), чтобы сгенерировать сообщение трассировки, которое python записывает в stderr при необработанных исключениях.

NB: я не пробовал, если он используется с ошибками MemoryException,но так вы ловите неисследованные исключения.

1 голос
/ 21 октября 2010

A MemoryError является исключением, вы должны быть в состоянии поймать его в блоке except.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...