Como faço para limpar todas as variáveis ​​no meio de um script Python?

88

Estou procurando algo semelhante a 'limpar' no Matlab: um comando / função que remove todas as variáveis ​​da área de trabalho, liberando-as da memória do sistema. Existe tal coisa em Python?

EDIT: Eu quero escrever um script que em algum momento apaga todas as variáveis.

serpenteante
fonte
2
Será útil alterar o título para algo como "Como faço para limpar todas as variáveis ​​no meio de um script Python?" para pesquisas futuras sobre o tema, pois "Como reiniciar a janela de comando em Python?" não tem nada a ver com o que você está realmente pedindo.
Sam Dolan
Você pode fornecer algum contexto possível em que isso faça sentido?
S.Lott
2
Parece mais um caso de tentativa de mudança de hábitos de codificação de seu ambiente nativo para outro em que não façam sentido.
Glenn Maynard
Se você está preocupado apenas com alguns objetos massivos (imagens ou outras matrizes enormes), poderá vê- dellos quando terminar. Se você está simplesmente preocupado com o namespace sendo desordenado, você provavelmente deve reconsiderar seu design usando tantos nomes. Por exemplo, para uma série de transformações de imagem, manter cada etapa intermediária provavelmente é desnecessário.
Nick T
4
@ S.Lott: análise científica exploratória em um console. É comum acabar com muitas variáveis ​​indesejáveis ​​(depois de tentar coisas e decidir que esse não é um caminho relevante). Mas, neste caso, a resposta de John La Rooy é a mais adequada.
naught101

Respostas:

70

A seguinte sequência de comandos remove todos os nomes do módulo atual:

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

Duvido que você realmente queira fazer isso, porque "todo nome" inclui todos os embutidos, então não há muito que você possa fazer após uma eliminação total. Lembre-se, em Python não existe realmente algo como uma "variável" - existem objetos , de muitos tipos (incluindo módulos, funções, classes, números, strings, ...), e existem nomes , vinculados a objetos; o que a sequência faz é remover todos os nomes de um módulo (os objetos correspondentes desaparecem se e somente se todas as referências a eles tiverem acabado de ser removidas).

Talvez você queira ser mais seletivo, mas é difícil adivinhar exatamente o que você quer dizer, a menos que queira ser mais específico. Mas, só para dar um exemplo:

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

Essa sequência deixa de lado os nomes que são privados ou mágicos, incluindo o __builtins__nome especial que abriga todos os nomes embutidos. Portanto, os integrados ainda funcionam - por exemplo:

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

Como você pode ver, name n(a variável de controle fornele) também permanece (já que é religado na forcláusula toda vez), então pode ser melhor nomear essa variável de controle _, por exemplo, para mostrar claramente "é especial "(mais, no interpretador interativo, o nome _é reconectado de qualquer maneira após cada expressão completa inserida no prompt, ao valor daquela expressão, de modo que não permanecerá por muito tempo ;-).

De qualquer forma, uma vez que você tenha determinado exatamente o que é que você quer fazer, não é difícil de definir uma função para o efeito e colocá-lo em seu arquivo de start-up (se quiser apenas em sessões interativas) ou arquivo local-personalize ( se você quiser em cada script).

Alex Martelli
fonte
2
Bem, você sempre pode manter uma cópia do dicionário original na inicialização e, em seguida, remover os nomes que foram adicionados;) No entanto, acho que isso é um abuso claro do sistema dinâmico, e não consigo pensar em uma situação sem sentido para fazer isso pol.
monoceres de
5
Haha, este é brilhante ... É surpreendente a quantidade de funcionalidade que você perde ao fazer isso, e ainda quanta funcionalidade você pode voltar, fazendo coisas como int = (2).__class__, str = ''.__class__, True = (1 == 1)etc ...
Chinmay Kanchi
@monoceres, como você nomearia essa cópia e onde você a esconderia para que não fosse apagada também? -)
Alex Martelli
2
Quanto mais eu uso o Python, mais o adoro. Além de ser um ótimo idioma, você também pode passar horas simplesmente brincando com ele e fazendo com que ele faça coisas que você realmente não deveria ;-)
Chinmay Kanchi
1
Talvez eu tenha entendido errado, mas me deparei com um problema: quando você usa for n in dir(): ... if n[0]!='_': delattr(this, n)em algum momento n=thise deleta do loop! Portanto, na próxima iteração você obterá Erro ao tentar delattr(this,n)porque acabou de excluí-lo! :) Então não funciona corretamente
Mikhail_Sam
59

Não, é melhor reiniciar o intérprete

IPython é um excelente substituto para o interpretador empacotado e tem o %resetcomando que geralmente funciona

John La Rooy
fonte
1
Por 'não' você quer dizer que eu não deveria fazer isso ou que é impossível? Se você disser que eu não deveria fazer isso, você poderia explicar por quê?
snakile de
6
+1: Leva menos de um quarto de segundo para eu ctrl-dentão pyt-> tabvoltar ao intérprete. Não há razão para fazer nada extravagante aqui.
Sam Dolan
3
% reset funciona para a maioria das variáveis, para algumas não. Para mim, apenas reiniciar o intérprete garante a limpeza de tudo.
artemis_clyde
3
Use %reset -fpara ser não interativo. stackoverflow.com/questions/38798181/…
Joachim Wagner
28

Se você escrever uma função, depois de deixá-la, todos os nomes dentro dela desaparecem.

O conceito é chamado de namespace e é tão bom que chegou ao Zen do Python :

Os namespaces são uma ótima ideia - vamos fazer mais disso!

O namespace do IPython também pode ser redefinido com o comando mágico %reset -f. (O -fsignifica "forçar"; em outras palavras, "não me pergunte se eu realmente quero deletar todas as variáveis, apenas faça".

Jochen Ritzel
fonte
1
Vou acrescentar o óbvio: se você colocar tudo dentro de uma função principal (incluindo importações), você obtém na prática um local de trabalho que pode redefinir apenas saindo dessa função. Eu acredito que é exatamente para isso que a pergunta se destina.
David,
8
from IPython import get_ipython;   
get_ipython().magic('reset -sf')
Anurag Gupta
fonte
3
Por favor, dê uma olhada em Como responder
Adonis
1
ou simplesmente%reset -sf
Bal Krishna Jha
1
na verdade, o comando% reset -sf não funciona e gera um erro, quando você executa seu script python com o prompt do anaconda (mesmo quando você usa try- except; não está funcionando). Você pode tentar o mesmo e verá. Porém, o uso da biblioteca ipython resolverá esse problema, em todos os casos possíveis.
Anurag Gupta de
5

Esta é uma versão modificada da resposta de Alex. Podemos salvar o estado do namespace de um módulo e restaurá-lo usando os 2 métodos a seguir ...

__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

Você também pode adicionar uma linha "clear = restoreContext" antes de chamar saveContext () e clear () funcionará como o clear do matlab.

Jarro
fonte
1
Ótima resposta! Acredito que para Python 3 você deseje ajustar o restoreContext com names = list(sys.modules[__name__].__dict__.keys()), caso contrário, o Python reclamará que você alterou o tamanho do dicionário enquanto iterava por meio de seu dict_keysobjeto.
Sam Bader,
Além disso, para aqueles que desejam importesta resposta (ou seja, salvei isso e importei de um bloco de anotações Jupyter para limpar o espaço de nomes entre os diferentes problemas em uma tarefa de casa), acho que você vai querer usar em "__main__"vez de __name__.
Sam Bader,
3

No Spyder, pode-se configurar o console IPython para cada arquivo Python para limpar todas as variáveis ​​antes de cada execução no Menu Run -> Configuration -> General settings -> Remove all variables before execution.

tardis
fonte
2

A globals()função retorna um dicionário, onde as chaves são nomes de objetos que você pode nomear (e os valores, a propósito, são ids desses objetos). A exec()função pega uma string e a executa como se você apenas a digitasse em um console Python. Então, o código é

for i in list(globals().keys()):
    if(i[0] != '_'):
        exec('del {}'.format(i))
Kolay.Ne
fonte
Embora este snippet de código possa resolver a questão, incluir uma explicação ajuda a melhorar a qualidade de sua resposta. Lembre-se de que você está respondendo à pergunta para leitores no futuro, e essas pessoas podem não saber os motivos de sua sugestão de código.
Stefan Crain,
Obrigado. Agora está melhor?
Kolay.Ne
0

No IDE ocioso, há Shell / Reiniciar Shell. Cntrl-F6 fará isso.

Harold Henson
fonte
0

Não é a maneira mais fácil de criar uma classe contendo todas as variáveis ​​necessárias? Então você tem um objeto com todas as variáveis ​​atuais e, se precisar, pode sobrescrever essa variável?

Ivan
fonte