¿Cómo borro todas las variables en medio de una secuencia de comandos de Python?

86

Estoy buscando algo similar a 'borrar' en Matlab: un comando / función que elimina todas las variables del espacio de trabajo y las libera de la memoria del sistema. ¿Existe tal cosa en Python?

EDITAR: Quiero escribir un script que en algún momento borre todas las variables.

Snakile
fuente
2
Será útil si cambia su título a algo como "¿Cómo borro todas las variables en medio de una secuencia de comandos de Python?" para futuras búsquedas sobre el tema, porque "¿Cómo reiniciar la ventana de comandos en Python?" no tiene nada que ver con lo que realmente estás preguntando.
Sam Dolan
¿Puede proporcionar algún contexto posible en el que esto tenga sentido?
S.Lott
2
Suena como otro caso de intentar trasladar los hábitos de codificación de su entorno nativo a uno en el que no tienen ningún sentido.
Glenn Maynard
Si solo le preocupan algunos objetos masivos (imágenes u otras matrices enormes), puede delusarlos cuando haya terminado. Si simplemente le preocupa que el espacio de nombres esté desordenado, probablemente debería reconsiderar su diseño usando tantos nombres. Por ejemplo, para una serie de transformaciones de imagen, es probable que no sea necesario mantener todos los pasos intermedios.
Nick T
3
@ S.Lott: análisis científico exploratorio en una consola. Es común terminar con muchas variables no deseadas (después de probar cosas y luego decidir que esa no es una vía relevante). Pero en este caso, la respuesta de John La Rooy es la más adecuada.
naught101

Respuestas:

69

La siguiente secuencia de comandos elimina todos los nombres del módulo actual:

>>> import sys
>>> sys.modules[__name__].__dict__.clear()

Dudo que realmente quieras hacer esto, porque "todos los nombres" incluyen todos los componentes integrados, por lo que no hay mucho que puedas hacer después de una eliminación tan total. Recuerde, en Python realmente no existe tal cosa como una "variable" - hay objetos , de muchos tipos (incluyendo módulos, funciones, clases, números, cadenas, ...), y hay nombres ligados a objetos; lo que hace la secuencia es eliminar todos los nombres de un módulo (los objetos correspondientes desaparecen si y solo si se acaba de eliminar cada referencia a ellos).

Tal vez quieras ser más selectivo, pero es difícil adivinar exactamente a qué te refieres a menos que quieras ser más específico. Pero, solo para dar un ejemplo:

>>> import sys
>>> this = sys.modules[__name__]
>>> for n in dir():
...   if n[0]!='_': delattr(this, n)
... 
>>>

Esta secuencia deja solo los nombres que son privados o mágicos, incluido el __builtins__nombre especial que alberga todos los nombres incorporados. Por lo tanto, los elementos integrados siguen funcionando, por ejemplo:

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'n']
>>> 

Como ves, nombre n (la variable de control en eso for) también se mantiene (ya que se vuelve a unir en la forcláusula cada vez que se completa), por lo que podría ser mejor nombrar esa variable de control _, por ejemplo, para mostrar claramente "es especial "(además, en el intérprete interactivo, el nombre _se vuelve a vincular de todos modos después de cada expresión completa ingresada en el indicador, al valor de esa expresión, por lo que no se quedará por mucho tiempo ;-).

De todos modos, una vez que haya determinado exactamente qué es lo que desea hacer, no es difícil definir una función para el propósito y ponerla en su archivo de inicio (si lo desea solo en sesiones interactivas) o en el archivo de personalización del sitio ( si lo desea en cada guión).

Alex Martelli
fuente
2
Bueno, siempre puede mantener una copia del diccionario original al inicio y luego eliminar los nombres que se han agregado;) Sin embargo, creo que esto es un abuso claro del sistema dinámico, y no puedo pensar en una situación sin sentido para hacer esto in.
monoceres
5
Jaja, esto es brillante ... Es sorprendente la cantidad de funcionalidad se pierde al hacer esto, y sin embargo la cantidad de funcionalidad que pueda volver al hacer cosas por el estilo int = (2).__class__, str = ''.__class__, True = (1 == 1)etc ...
Chinmay Kanchi
@monoceres, ¿cómo nombrarías esa copia y dónde la esconderías para que no se borre también? -)
Alex Martelli
2
Cuanto más uso Python, más lo amo. No solo es un gran lenguaje, también puedes pasar horas simplemente jugando con él y haciendo que haga cosas que realmente no deberías ;-)
Chinmay Kanchi
1
Tal vez lo entendí de manera incorrecta, pero me enfrenté a un problema: ¡cuando lo usas for n in dir(): ... if n[0]!='_': delattr(this, n)en algún momento n=thisy lo eliminas en el ciclo! Entonces, en la siguiente iteración, aparece Error al intentarlo delattr(this,n)porque lo acaba de eliminar. :) Entonces no funciona correctamente
Mikhail_Sam
60

No, es mejor reiniciar el intérprete

IPython es un excelente reemplazo para el intérprete incluido y tiene el %resetcomando que generalmente funciona

John La Rooy
fuente
1
¿Con "No" te refieres a que no debería hacerlo o que es imposible? Si dices que no debería hacerlo, ¿podrías explicar por qué?
Snakile
6
+1: Me toma menos de un cuarto de segundo ctrl-dentonces pyt-> tabvolver al intérprete. No hay razón para hacer nada elegante aquí.
Sam Dolan
3
% reset funciona para la mayoría de las variables, para algunas no. Para mí, solo reiniciar el intérprete garantiza limpiar todo.
artemis_clyde
3
Utilice %reset -fpara no ser interactivo. stackoverflow.com/questions/38798181/…
Joachim Wagner
27

Si escribe una función, una vez que la deje, todos los nombres dentro desaparecerán.

El concepto se llama espacio de nombres y es tan bueno que se convirtió en el Zen de Python :

Los espacios de nombres son una gran idea, ¡hagamos más!

El espacio de nombres de IPython también se puede restablecer con el comando mágico %reset -f. ( -fSignifica "forzar"; en otras palabras, "no me preguntes si realmente quiero eliminar todas las variables, simplemente hazlo").

Jochen Ritzel
fuente
Agregaré lo obvio: si pones todo dentro de una función principal (incluidas las importaciones), obtienes en la práctica un lugar de trabajo que puedes restablecer simplemente saliendo de esa función. Creo que eso es, de hecho, para lo que estaba destinada la pregunta.
David
8
from IPython import get_ipython;   
get_ipython().magic('reset -sf')
Anurag Gupta
fuente
3
Por favor, eche un vistazo a Cómo responder
Adonis
1
o simplemente%reset -sf
सत्यमेव जयते
1
en realidad, el comando% reset -sf no funciona y arroja un error, cuando ejecuta su script de Python con el símbolo del sistema anaconda (aunque cuando haya usado try- excepto; no está funcionando). Puedes intentar lo mismo y verás. Pero, el uso de la biblioteca ipython resolverá este problema, en todos los casos posibles.
Anurag Gupta
5

Esta es una versión modificada de la respuesta de Alex. Podemos guardar el estado del espacio de nombres de un módulo y restaurarlo usando los siguientes 2 métodos ...

__saved_context__ = {}

def saveContext():
    import sys
    __saved_context__.update(sys.modules[__name__].__dict__)

def restoreContext():
    import sys
    names = sys.modules[__name__].__dict__.keys()
    for n in names:
        if n not in __saved_context__:
            del sys.modules[__name__].__dict__[n]

saveContext()

hello = 'hi there'
print hello             # prints "hi there" on stdout

restoreContext()

print hello             # throws an exception

También puede agregar una línea "clear = restoreContext" antes de llamar a saveContext () y clear () funcionará como clear de matlab.

Jarra
fuente
1
¡Gran respuesta! Creo que para Python 3 querrá modificar restoreContext names = list(sys.modules[__name__].__dict__.keys()), de lo contrario, Python se quejará de que ha cambiado el tamaño del diccionario mientras itera a través de su dict_keysobjeto.
Sam Bader
Además, para aquellos que quieran importesta respuesta (es decir, tengo esto guardado e importo esto desde un cuaderno de Jupyter para borrar el espacio de nombres entre diferentes problemas en una tarea), creo que querrán usar en "__main__"lugar de __name__.
Sam Bader
3

En Spyder se puede configurar la consola IPython para cada archivo Python para borrar todas las variables antes de cada ejecución en el Menú Run -> Configuration -> General settings -> Remove all variables before execution.

tardis
fuente
2

La globals()función devuelve un diccionario, donde las claves son nombres de objetos que puede nombrar (y los valores, por cierto, son ids de estos objetos). La exec()función toma una cadena y la ejecuta como si la escribiera en una consola de Python. Entonces, el código es

for i in list(globals().keys()):
    if(i[0] != '_'):
        exec('del {}'.format(i))
Kolay.Ne
fuente
Si bien este fragmento de código puede resolver la pregunta, incluir una explicación ayuda a mejorar la calidad de su respuesta. Recuerde que está respondiendo a la pregunta para los lectores en el futuro, y es posible que esas personas no conozcan los motivos de su sugerencia de código.
Stefan Crain
Gracias. ¿Está mejor ahora?
Kolay.Ne
0

En el IDE inactivo hay Shell / Restart Shell. Cntrl-F6 lo hará.

Harold Henson
fuente
0

¿No es la forma más fácil de crear una clase continuando con todas las variables necesarias? Entonces tiene un objeto con todas las variables actuales, y si lo necesita, ¿puede sobrescribir esta variable?

Iván
fuente