punteros objetos objeto memoria manejo maneja eliminar dinámica destruir como asignación python debugging memory-management memory-leaks

objetos - Fugas de memoria de Python



punteros en python (9)

Echa un vistazo a este artículo: rastreo de fugas de memoria de Python

Además, tenga en cuenta que el módulo de recolección de basura en realidad puede tener indicadores de depuración establecidos. Mira la función set_debug . Además, consulte este código por Gnibbler para determinar los tipos de objetos que se han creado después de una llamada.

Tengo un script de larga duración que, si lo dejo funcionar lo suficiente, consumirá toda la memoria de mi sistema.

Sin entrar en detalles sobre el guión, tengo dos preguntas:

  1. ¿Hay alguna "Mejores Prácticas" a seguir, que ayudará a prevenir las fugas?
  2. ¿Qué técnicas existen para depurar fugas de memoria en Python?

En cuanto a las mejores prácticas, esté atento a las funciones recursivas. En mi caso, tuve problemas con la recursión (donde no era necesario). Un ejemplo simplificado de lo que estaba haciendo:

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

Operar de esta manera recursiva no desencadenará la recolección de basura y eliminará los restos de la función, por lo que cada vez que el uso de memoria crece y crece.

Mi solución fue sacar la llamada recursiva de my_function () y hacer que main () manejara cuándo volver a llamar. de esta manera, la función finaliza naturalmente y se limpia después de sí misma.

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


Especialmente debe echar un vistazo a sus datos globales o estáticos (datos de larga duración).

Cuando estos datos crecen sin restricciones, también puede tener problemas en Python.

El recolector de basura solo puede recopilar datos, que ya no se referencian. Pero sus datos estáticos pueden conectar elementos de datos que deberían liberarse.

Otro problema pueden ser los ciclos de memoria, pero al menos, en teoría, el recolector de basura debería encontrar y eliminar ciclos, al menos mientras no estén enganchados a algunos datos vivientes largos.

¿Qué tipos de datos de larga vida son especialmente problemáticos? Eche un vistazo a las listas y diccionarios: pueden crecer sin límite. En los diccionarios, es posible que incluso no vea el problema, ya que cuando acceda a dicts, la cantidad de claves en el diccionario puede no ser de gran visibilidad para usted ...


Esto de ninguna manera es un consejo exhaustivo. Pero lo más importante a tener en cuenta al escribir con la idea de evitar fugas de memoria futuras (bucles) es asegurarse de que cualquier cosa que acepte una referencia a una devolución de llamada, almacene esa devolución de llamada como una referencia débil.


No estoy seguro acerca de las "Mejores prácticas" para las fugas de memoria en Python, pero Python debe borrar su propia memoria por su recolector de basura. Entonces, principalmente comenzaría por buscar una lista circular de algunos cortos, ya que no serán recogidos por el recolector de basura.


Para detectar y localizar fugas de memoria para procesos de larga ejecución, por ejemplo, en entornos de producción, ahora puede usar stackimpact . Utiliza tracemalloc debajo. Más información en esta publicación .


Permítanme recomendar la herramienta mem_top ,
eso me ayudó a resolver un problema similar.

Simplemente muestra al instante a los principales sospechosos de fugas de memoria en un programa de Python.


El módulo Tracemalloc se integró como un módulo integrado a partir de Python 3.4 y, al parecer, también está disponible para versiones anteriores de Python como una biblioteca de terceros (aunque aún no lo han probado).

Este módulo es capaz de generar los archivos y líneas precisos que asignaron la mayor cantidad de memoria. En mi humilde opinión, esta información es infinitamente más valiosa que el número de instancias asignadas para cada tipo (que termina siendo muchas tuplas el 99% del tiempo, lo cual es una pista, pero apenas ayuda en la mayoría de los casos).

Recomiendo que uses tracemalloc en combinación con pyrasite . 9 de cada 10 veces, ejecutar el fragmento de los 10 primeros en un pyrasite-shell le dará suficiente información y sugerencias para arreglar la fuga en 10 minutos. Sin embargo, si aún no puede encontrar la causa de la fuga, pyrasite-shell en combinación con las otras herramientas mencionadas en este hilo probablemente le dará más pistas. También debe echar un vistazo a todos los ayudantes adicionales proporcionados por pyrasite (como el visor de memoria).


pympler mayoría de las opciones mencionadas anteriormente pero encontré que este paquete pequeño e intuitivo es el mejor:

Es bastante sencillo rastrear objetos que no fueron recolectados como basura, consulte este pequeño ejemplo:

instalar el paquete a través de pip install pympler

from pympler.tracker import SummaryTracker tracker = SummaryTracker() # ... some code you want to investigate ... tracker.print_diff()

El resultado muestra todos los objetos que se han agregado, más la memoria que consumieron.

Muestra de salida:

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

Este paquete proporciona varias características más. Verifique la documentación de la impresora , en particular la sección Identificación de fugas de memoria .