Recogida de basura de python

He creado un código de Python que crea un objeto en un bucle y en cada iteración sobrescribe este objeto con uno nuevo del mismo tipo. Esto se realiza 10.000 veces, y Python ocupa 7 MB de memoria cada segundo hasta que se utiliza mi RAM de 3 gb. ¿Alguien sabe de una manera de eliminar los objetos de la memoria?

No ha proporcionado suficiente información; esto depende de los detalles específicos del objeto que está creando y qué más está haciendo con él en el bucle. Si el objeto no crea referencias circulares, debe desasignarse en la siguiente iteración. Por ejemplo, el código

for x in range(100000): obj = " " * 10000000 

no dará lugar a una asignación de memoria cada vez mayor.

Creo que esto es una referencia circular (aunque la pregunta no es explícita sobre esta información).

Una forma de resolver este problema es invocar manualmente la recolección de basura. Cuando ejecute manualmente el recolector de basura, también barrerá los objetos de referencia circulares.

 import gc for i in xrange(10000): j = myObj() processObj(j) #assuming count reference is not zero but still #object won't remain usable after the iteration if !(i%100): gc.collect() 

Aquí no ejecute el recolector de basura con demasiada frecuencia porque tiene su propia sobrecarga, por ejemplo, si ejecuta el recolector de basura en cada ciclo, la interpretación será extremadamente lenta.

Este es un error antiguo que se corrigió para algunos tipos en Python 2.5. Lo que estaba sucediendo era que Python no era tan bueno en la recostackción de listas vacías / diccionarios / tupes / floats / ints. En Python 2.5 esto fue arreglado … en su mayoría. Sin embargo, los flotadores y los ints son únicos para las comparaciones, por lo que una vez que se crea uno de ellos, permanece activo mientras el intérprete esté vivo. Me ha mordido esto peor cuando trato con una gran cantidad de carrozas, ya que tienen la mala costumbre de ser únicos. Esto se caracterizó por Python 2.4 y se actualizó acerca de su plegado en Python 2.5.

La mejor manera de encontrarlo es actualizarse a Python 2.5 o más reciente para encargarse del problema de las listas / diccionarios / tuplas. Para los números, la única solución es no permitir que grandes cantidades de números ingresen a Python. Lo he hecho con mi propio envoltorio para un objeto c ++, pero tengo la impresión de que numpy.array dará resultados similares.

Como secuencia de comandos posterior, no tengo idea de lo que ha sucedido con Python 3, pero sospecho que los números siguen siendo parte de un singleton. Así que la pérdida de memoria es en realidad una característica del lenguaje.

Si está creando referencias circulares, sus objetos no se desasignarán inmediatamente, sino que tendrán que esperar a que se ejecute un ciclo de GC.

Podría usar el módulo weakref para solucionar este problema, o delimitar explícitamente sus objetos después de su uso.

Descubrí que en mi caso (con Python 2.5.1), con referencias circulares que involucran clases que tienen __del__() , no solo la recolección de basura no estaba ocurriendo de manera oportuna, los __del__() de mis objetos nunca fueron llamados. , incluso cuando el script salió. Así que usé debilidad para romper las referencias circulares y todo estaba bien.

Felicitaciones a Miles, quien me proporcionó toda la información en sus comentarios para que lo pusiera todo junto.

Aquí hay una cosa que puede hacer en el REPL para forzar una desreferenciación de una variable:

 >>> x = 5 >>> x 5 >>> del x >>> x Traceback (most recent call last): File "", line 1, in  NameError: name 'x' is not defined 

weakref se puede utilizar para código estructurado de objeto circular como en el ejemplo explicado