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.


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).


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


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".


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')

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.


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.


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))

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

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?

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.