¿Hay alguna forma de eliminar las variables creadas, funciones, etc. de la memoria del intérprete?


113

He estado buscando la respuesta precisa a esta pregunta durante un par de días, pero no tengo nada bueno. No soy un principiante absoluto en programación, pero aún ni siquiera en el nivel intermedio.

Cuando estoy en el shell de Python, escribo: dir()y puedo ver todos los nombres de todos los objetos en el alcance actual (bloque principal), hay 6 de ellos:

['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

Luego, cuando declaro una variable, por ejemplo x = 10, se agrega automáticamente a esa lista de objetos en el módulo incorporado dir(), y cuando vuelvo a escribir dir(), se muestra ahora:

['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'x']

Lo mismo ocurre con las funciones, clases, etc.

¿Cómo elimino todos esos objetos nuevos sin borrar el estándar 6 que estaba disponible al principio?

He leído aquí sobre "limpieza de memoria", "limpieza de la consola", que borra todo el texto de la ventana del símbolo del sistema:

>>> import sys
>>> clear = lambda: os.system('cls')
>>> clear()

Pero todo esto no tiene nada que ver con lo que estoy tratando de lograr, no limpia todos los objetos usados.


2
¿Por qué sientes que necesitas hacer esto, o simplemente lo preguntas por curiosidad?
PM 2 Ring

Simplemente no sabía que había una delfunción ahí fuera. Estoy comenzando a aprender Python y, a menudo, tengo que experimentar en el shell, por lo que los nombres de variables estándar como xo a ymenudo ya están en uso y reiniciar el shell me lleva otros 15 segundos (ahora tengo una computadora portátil muy, muy vieja). Así que quería encontrar una forma de limpiar la memoria de Python más rápido.
funghorn

1
¡Ah! FWIW, delno es exactamente una función, por lo tanto, no (y ). Es una palabra clave que introduce una declaración del. Por supuesto, la forma en que realmente elimina un objeto puede involucrar funciones, pero esa es otra historia ...
PM 2 Ring

Cuando experimente en el shell, nombres como xo yno deberían estar en uso a menos que los esté usando. O a menos que hagas algo tonto como from _somemodule_ import *, entonces tendrás todo tipo de basura abarrotando el lugar. :)
PM 2 Ring

1
Busqué en Google esta pregunta y ahora me pregunto: ¿por qué no puedo simplemente reiniciar el kernel y volver a ejecutar el script desde la parte superior si quiero eliminar todas las variables y funciones de todos modos?
vagabond

Respuestas:


159

Puede eliminar nombres individuales con del:

del x

o puede eliminarlos del globals()objeto:

for name in dir():
    if not name.startswith('_'):
        del globals()[name]

Este es solo un bucle de ejemplo; De manera defensiva, solo elimina los nombres que no comienzan con un guión bajo, asumiendo (no sin razón) que solo usó nombres sin un guión bajo al principio en su intérprete. En su lugar, podría usar una lista codificada de nombres (lista blanca) si realmente quisiera ser minucioso. No hay una función incorporada para hacer la limpieza por usted, aparte de salir y reiniciar el intérprete.

Los módulos que ha importado ( import os) permanecerán importados porque son referenciados por sys.modules; las importaciones posteriores reutilizarán el objeto de módulo ya importado. Simplemente no tendrá una referencia a ellos en su espacio de nombres global actual.


Bueno, tengo que decir que startswith('_')parece bastante ingenuo. Si alguien es lo suficientemente inteligente como para escribir _foo=42o incluso __foo__=42, ¿cómo podemos eliminarlos? ¿Hay alguna forma de obtener los nombres de las propiedades del módulo estándar mediante programación?
georg

2
@georg: He codificado el bucle a la defensiva. Tendrá que codificar una lista inicial de nombres para mantener si desea hacerlo mejor.
Martijn Pieters

Entonces, ¿de ninguna manera? Mi pensamiento fue dir(ModuleType()), pero solo vuelve docy name.
georg

1
@georg: no; el espacio de nombres global del intérprete también varía de una versión a otra, y no hay una manera infalible (que yo sepa) de enumerar lo que había allí cuando abrió el intérprete en una etapa posterior .
Martijn Pieters

1
Las funciones y clases de @nakE son objetos como cualquier otro. No son especiales; use una lista blanca o verifique el tipo de objeto que necesita para preservar las clases y funciones.
Martijn Pieters

67

Si. Hay una forma sencilla de eliminar todo en iPython. En la consola iPython, simplemente escriba:

%reset

Entonces el sistema le pedirá que confirme. Presione y. Si no desea ver este mensaje, simplemente escriba:

%reset -f

Esto debería funcionar..


1
Una vez más, ¿por qué esta no es la mejor respuesta?
myradio

11
@myradio Porque es irrelevante para todos los que no usan IPython , y tampoco responde la pregunta; la pregunta pregunta cómo eliminar referencias de objetos globales, no restablecer el contenido del shell de IPython .
Andreas

17

Puede usar el recolector de basura de Python:

import gc
gc.collect()

6
¡Hola @Fardin! ¡Gracias! ¡Tu respuesta hizo el trabajo y me salvó el día! Pero antes de gc.collect () hice del (variable).
Gmosy Gnaq

9

Si se encuentra en un entorno interactivo como, Jupytero ipythonpodría estar interesado en eliminar las var no deseadas si se están volviendo pesadas.

Los comandos mágicos reset y reset_selectiveestá disponible en sesiones interactivas de Python como ipythonyJupyter

1) reset

reset Restablece el espacio de nombres eliminando todos los nombres definidos por el usuario, si se llama sin argumentos.

iny los outparámetros especifican si desea vaciar los cachés de entrada / salida. El historial del directorio se vacía con el dhistparámetro.

reset in out

Otro interesante es arrayque solo elimina numpy Arrays:

reset array

2) reset_selective

Restablece el espacio de nombres eliminando los nombres definidos por el usuario. El historial de entrada / salida se deja en caso de que lo necesite.

Ejemplo de matriz limpia:

In [1]: import numpy as np
In [2]: littleArray = np.array([1,2,3,4,5])
In [3]: who_ls
Out[3]: ['littleArray', 'np']
In [4]: reset_selective -f littleArray
In [5]: who_ls
Out[5]: ['np']

Fuente: http://ipython.readthedocs.io/en/stable/interactive/magics.html


6

Esto funcionó para mí.

Debe ejecutarlo dos veces una vez para globales seguidos por locales

for name in dir():
    if not name.startswith('_'):
        del globals()[name]

for name in dir():
    if not name.startswith('_'):
        del locals()[name]

4

En realidad, Python recuperará la memoria que ya no está en uso. Esto se llama recolección de basura, que es un proceso automático en Python. Pero aún así, si quieres hacerlo, puedes eliminarlo mediante del variable_name. También puedes hacerlo asignando la variable aNone

a = 10
print a 

del a       
print a      ## throws an error here because it's been deleted already.

La única forma de recuperar la memoria de los objetos Python sin referencia es a través del recolector de basura. La palabra clave del simplemente desvincula un nombre de un objeto, pero el objeto aún necesita ser recolectado como basura. Puede forzar la ejecución del recolector de basura utilizando el módulo gc, pero es casi seguro que se trata de una optimización prematura, pero tiene sus propios riesgos. El uso delno tiene ningún efecto real, ya que esos nombres se habrían eliminado ya que salieron del alcance de todos modos.


En efecto. Por supuesto, cuando se trabaja en el espacio de nombres global del intérprete, los nombres no van a quedar fuera de alcance, pero ¿y qué? :) Supongo que también vale la pena mencionar que lo que sucede con la memoria utilizada por los objetos que han sido recolectados como basura depende de la implementación, pero en la mayoría de las implementaciones de Python, la memoria gc'ed simplemente regresa al grupo de Python, no se devuelve al OS hasta que se cierre el programa.
PM 2 Ring

@ PM2Ring LOL :) Creo que sí. ¿De dónde te refieres para Python?
d-coder

2
Tenga en cuenta que en CPython, el GC solo es necesario para romper los ciclos de referencia. Si no quedan referencias, un objeto es elimina instantáneamente de la memoria. Así que del no tenga un efecto real aquí.
Martijn Pieters

@MartijnPieters, ¿eliminado instantáneamente? ¿Es un término técnico? :)
Eryk Sun

2
@eryksun: sí, como lo define RFC 4042-bis2, ¡por supuesto! :-P
Martijn Pieters
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.