MemoryError gancho en Python?

¿Hay alguna forma de interceptar globalmente las excepciones de MemoryError para que una biblioteca pueda borrar las cachés en lugar de dejar que el código de usuario vea un MemoryError?

Estoy desarrollando una biblioteca de almacenamiento en caché de memoria en Python que almacena objetos muy grandes, hasta el punto en que es común que los usuarios quieran usar toda la RAM disponible para simplificar sus scripts y / o acelerarlos. Me gustaría poder tener un gancho en el que el intérprete de python solicite a la función de callback que libere algo de RAM para evitar que se invoque un error de memoria en el código de usuario.

SO: Solaris y / o Linux

Python: cPython 2.6. *


EDITAR: Estoy buscando un mecanismo que no sea manejado por un bloque de excepción. Si hubiera un error de memoria en cualquier código por cualquier razón, me gustaría que el intérprete de Python primero intente usar una callback para liberar algo de RAM y nunca se genere la excepción MemoryError. No controlo el código que generaría los errores y me gustaría que mi caché fuera capaz de usar agresivamente la RAM que quiera, liberando automáticamente la RAM que necesite el código de usuario.

Esta no es una buena manera de manejar la administración de la memoria. Para cuando vea MemoryError, ya estará en un estado crítico en el que el kernel probablemente esté cerca de matar procesos para liberar memoria, y en muchos sistemas nunca lo verá porque se intercambiará o simplemente OOM. Mata tu proceso en lugar de fallar las asignaciones.

El único caso recuperable que es probable que vea MemoryError es después de intentar realizar una asignación muy grande que no se ajuste al espacio de direcciones disponible, solo es común en sistemas de 32 bits.

Si desea tener una memoria caché que libere memoria según sea necesario para otras asignaciones, no debe interactuar con los errores , sino con el asignador en sí. De esta manera, cuando necesite liberar memoria para una asignación, sabrá cuánta memoria contigua se necesita, o de lo contrario estará adivinando a ciegas. También significa que puede hacer un seguimiento de las asignaciones de memoria a medida que ocurren, por lo que puede mantener el uso de la memoria en un nivel específico, en lugar de dejar que crezca sin restricciones y luego tratar de recuperarse cuando se hace demasiado alto.

Sin embargo, sugiero firmemente que para la mayoría de las aplicaciones este tipo de comportamiento de almacenamiento en caché es demasiado complicado, por lo general es mejor usar una cantidad determinada de memoria para el caché.

Un MemoryError es una excepción, debería poder capturarlo en un bloque except .

Desearía poder comentar sobre la respuesta de Glenn … aunque estoy de acuerdo con la idea general de no usar la excepción MemoryException como forma de manejar el tamaño de la memoria caché, no significa necesariamente que su sistema sea nuestro objective cuando los detecte. Algunas personas corren sin cambiar, y también puede obtenerlas cuando usa ulimit para limitar el tamaño máximo del proceso. Además, al usar los límites suaves, incluso podría boost el límite suave para manejar con gracia el proceso de la propia muerte en el agotamiento de la memoria (suponiendo que haya una forma de boostla sin asignar más memoria; nunca lo intenté).

Atrapar una excepción no capturada significa que algo salió mal y no sabes qué. Esto significa que su aplicación puede comenzar a comportarse de manera inesperada, ¡como si comenzara a eliminar líneas de códigos al azar! Utilicé un controlador de excepciones genérico en algunas aplicaciones, pero solo para mostrar un mensaje agradable al usuario (especialmente útil con GUI) y desaparecer.

Puede enganchar su controlador de excepciones como esto:

 sys.excepthook =  

Los parámetros son la clase de excepción, la instancia de excepción y un objeto de rastreo. Puede pasar estos parámetros en el mismo orden a traceback.format_exception () para generar el mensaje de rastreo que Python escribe en stderr en excepciones no detectadas.

NB: No lo he intentado si es de alguna utilidad con los errores de MemoryException, pero esta es la forma en que se detectan las excepciones no detectadas.