he encontrado un problema con exec
(Sucedió en un sistema que tiene que ser extensible con guiones escritos por el usuario). Podría reducir el problema en sí a este código:Python: sentencia exec y el comportamiento recolector de basura inesperada
def fn():
context = {}
exec '''
class test:
def __init__(self):
self.buf = '1'*1024*1024*200
x = test()''' in context
fn()
que se espera que la memoria debe ser liberado por el recolector de basura después de la llamada de la función fn
. Sin embargo, el proceso de Python aún consume los 200 MB adicionales de memoria y no tengo ni idea de qué está sucediendo aquí y cómo liberar la memoria asignada manualmente.
Sospecho que la definición de una clase dentro de exec
no es una idea muy brillante, pero, antes que nada, quiero entender qué está fallando en el ejemplo anterior.
Parece que la creación de instancias de clases de envoltura en otra función se soluciona el problema, pero ¿cuál es la diferencia?
def fn():
context = {}
exec '''
class test:
def __init__(self):
self.buf = '1'*1024*1024*200
def f1(): x = test()
f1()
''' in context
fn()
Esta es mi versión intérprete de Python:
$ python
Python 2.7 (r27:82500, Sep 16 2010, 18:02:00)
[GCC 4.5.1 20100907 (Red Hat 4.5.1-3)] on linux2
¿Hacer lo mismo en su código (sin pasar por una cadena y 'exec') da los mismos resultados? – delnan
'gc.collect()' parece resolverlo. Debe haber un ciclo cíclico en alguna parte. Adivinando salvajemente, x tiene una referencia a su clase, la clase probablemente tiene una referencia al espacio de nombre en el que está definida, y que a su vez tiene una referencia de regreso a x. –
Lo mismo ocurre en mi código sin que el administrador funcione bien, y el recolector de basura funciona como se esperaba. – 3xter