Wie lösche ich alle Variablen in der Mitte eines Python-Skripts?

84

Ich suche nach etwas ähnlichem wie 'clear' in Matlab: Ein Befehl / eine Funktion, die alle Variablen aus dem Arbeitsbereich entfernt und sie aus dem Systemspeicher freigibt. Gibt es so etwas in Python?

EDIT: Ich möchte ein Skript schreiben, das irgendwann alle Variablen löscht.

Snakile
quelle
2
Es ist hilfreich, wenn Sie Ihren Titel in "Wie lösche ich alle Variablen in der Mitte eines Python-Skripts?" Geändert haben. für zukünftige Suchvorgänge zum Thema, weil "Wie starte ich das Befehlsfenster in Python neu?" hat nichts mit dem zu tun, was du eigentlich fragst.
Sam Dolan
Können Sie einen möglichen Kontext angeben, in dem dies sinnvoll ist?
S.Lott
2
Klingt nach einem weiteren Fall, in dem versucht wird, Codierungsgewohnheiten von ihrer ursprünglichen Umgebung in eine Umgebung zu verschieben, in der sie keinen Sinn ergeben.
Glenn Maynard
Wenn Sie sich nur um einige massive Objekte (Bilder oder andere große Arrays) sorgen, können Sie deldiese nach Abschluss ausführen. Wenn Sie sich nur Sorgen machen, dass der Namespace überfüllt ist, sollten Sie Ihr Design wahrscheinlich mit so vielen Namen überdenken. Beispielsweise ist es für eine Reihe von Bildtransformationen wahrscheinlich nicht erforderlich, jeden Zwischenschritt beizubehalten.
Nick T
3
@ S.Lott: explorative wissenschaftliche Analyse in einer Konsole. Es kommt häufig vor, dass viele unerwünschte Variablen verwendet werden (nachdem Sie Dinge ausprobiert und dann entschieden haben, dass dies kein relevanter Pfad ist). In diesem Fall ist die Antwort von John La Rooy am besten geeignet.
naught101

Antworten:

69

Die folgende Befehlsfolge entfernt jeden Namen aus dem aktuellen Modul:

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

Ich bezweifle, dass Sie dies tatsächlich tun möchten, da "jeder Name" alle integrierten Funktionen enthält, sodass Sie nach einem solchen vollständigen Auslöschen nicht viel tun können. Denken Sie daran, dass es in Python wirklich keine "Variable" gibt - es gibt Objekte verschiedener Art (einschließlich Module, Funktionen, Klassen, Zahlen, Zeichenfolgen, ...) und Namen , die an Objekte gebunden sind. Die Sequenz entfernt jeden Namen aus einem Modul (die entsprechenden Objekte verschwinden genau dann, wenn jeder Verweis auf sie gerade entfernt wurde).

Vielleicht möchten Sie selektiver sein, aber es ist schwer zu erraten, was Sie genau meinen, es sei denn, Sie möchten spezifischer sein. Aber nur um ein Beispiel zu geben:

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

Diese Sequenz hinterlässt private oder magische Namen, einschließlich des __builtins__speziellen Namens, der alle integrierten Namen enthält. Einbauten funktionieren also immer noch - zum Beispiel:

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

Wie Sie sehen, bleibt auch nder Name (die darin enthaltene Steuervariable for) bestehen (da er forjedes Mal in der Klausel neu gebunden wird ). Daher ist es möglicherweise besser, diese Steuervariable zu benennen _, um beispielsweise deutlich zu zeigen, dass sie vorhanden ist special "(plus, im interaktiven Interpreter wird der Name _ohnehin nach jedem vollständigen Ausdruck, der an der Eingabeaufforderung eingegeben wird, auf den Wert dieses Ausdrucks neu gebunden, damit er nicht lange anhält ;-).

Wie auch immer, wenn Sie genau bestimmt haben , was es ist etwas Sie tun wollen, ist es nicht schwer , eine Funktion für den Zweck zu definieren und sie in Ihrer Start-up - Datei (wenn Sie es in interaktiven Sitzungen nur wollen) oder Website-fertige Datei ( wenn Sie es in jedem Skript wollen).

Alex Martelli
quelle
2
Nun, Sie könnten beim Start immer eine Kopie des Originalwörterbuchs behalten und dann hinzugefügte Namen entfernen;) Ich denke jedoch, dass dies ein klarer Missbrauch des dynamischen Systems ist, und ich kann mir keine sinnlose Situation vorstellen, um dies zu tun in.
Monoceres
5
Haha, das ist brillant ... Es ist erstaunlich , wie viel Funktionalität , die Sie , indem Sie diese verlieren, und doch , wie viel Funktionalität können Sie , indem Sie solche Sachen zurück int = (2).__class__, str = ''.__class__, True = (1 == 1)etc ...
Chinmay Kanchi
@ Monoceres, wie würden Sie diese Kopie benennen und wo würden Sie sie verstecken, damit sie nicht auch weggewischt wird? -)
Alex Martelli
2
Je öfter ich Python benutze, desto mehr liebe ich es. Es ist nicht nur eine großartige Sprache, Sie können auch Stunden damit verbringen, einfach damit
herumzuspielen
1
Vielleicht habe ich es falsch verstanden, aber ich hatte ein Problem: Wenn Sie es for n in dir(): ... if n[0]!='_': delattr(this, n)irgendwann verwenden n=thisund es in der Schleife löschen! Bei der nächsten Iteration tritt also ein Fehler beim Versuch auf, delattr(this,n)weil Sie ihn gerade gelöscht haben! :) Also funktioniert es nicht richtig
Mikhail_Sam
60

Nein, am besten starten Sie den Interpreter neu

IPython ist ein hervorragender Ersatz für den mitgelieferten Interpreter und verfügt über den %resetBefehl, der normalerweise funktioniert

John La Rooy
quelle
1
Mit "Nein" meinst du, ich sollte es nicht tun oder dass es unmöglich ist? Wenn Sie sagen, ich sollte es nicht tun, können Sie erklären, warum?
Snakile
6
+1: Es dauert weniger als eine Viertelsekunde für mich ctrl-ddann pyt-> tabin den Interpreter zurück zu bekommen. Kein Grund, hier etwas Besonderes zu tun.
Sam Dolan
3
% reset funktioniert für die meisten Variablen, für einige nicht. Nur ein Neustart des Dolmetschers garantiert für mich die Reinigung.
Artemis_clyde
3
Verwenden Sie %reset -fdiese Option , um nicht interaktiv zu sein. stackoverflow.com/questions/38798181/…
Joachim Wagner
27

Wenn Sie eine Funktion schreiben, verschwinden alle Namen, sobald Sie sie belassen.

Das Konzept heißt Namespace und ist so gut, dass es in das Zen von Python gelangt ist :

Namespaces sind eine großartige Idee - lasst uns mehr davon machen!

Der Namespace von IPython kann ebenfalls mit dem Befehl magic zurückgesetzt werden %reset -f. (Das -fbedeutet "Kraft"; mit anderen Worten: "Frag mich nicht, ob ich wirklich alle Variablen löschen möchte, mach es einfach.")

Jochen Ritzel
quelle
Ich füge das Offensichtliche hinzu: Wenn Sie alles in eine Hauptfunktion (einschließlich Importe) einfügen, erhalten Sie in der Praxis einen Arbeitsplatz, den Sie zurücksetzen können, indem Sie diese Funktion beenden. Ich glaube, genau dafür war die Frage gedacht.
David
8
from IPython import get_ipython;   
get_ipython().magic('reset -sf')
Anurag Gupta
quelle
3
Bitte werfen Sie einen Blick auf How to Answer
Adonis
1
oder einfach%reset -sf
जयते जयते
1
Tatsächlich funktioniert der Befehl% reset -sf nicht und löst einen Fehler aus, wenn Sie Ihr Python-Skript mit einer Anaconda-Eingabeaufforderung ausführen (obwohl Sie try- außer verwendet haben; es funktioniert nicht). Sie können das gleiche versuchen und Sie werden sehen. Die Verwendung der ipython-Bibliothek löst dieses Problem jedoch in jedem möglichen Fall.
Anurag Gupta
5

Dies ist eine modifizierte Version von Alex 'Antwort. Wir können den Status des Namespace eines Moduls speichern und mithilfe der folgenden 2 Methoden wiederherstellen ...

__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

Sie können auch eine Zeile "clear = restoreContext" hinzufügen, bevor Sie saveContext () aufrufen, und clear () funktioniert wie matlab's clear.

Krug
quelle
1
Gute Antwort! Ich glaube, für Python 3 möchten Sie restoreContext optimieren names = list(sys.modules[__name__].__dict__.keys()), andernfalls beschwert sich Python, dass Sie die Wörterbuchgröße geändert haben, während Sie das dict_keysObjekt durchlaufen .
Sam Bader
Auch für diejenigen, die auf importdiese Antwort antworten möchten (dh ich habe diese gespeichert und importiere sie aus einem Jupyter-Notizbuch, um den Namespace zwischen verschiedenen Problemen in einer Hausaufgabe zu löschen), denke ich, dass Sie "__main__"stattdessen verwenden möchten __name__.
Sam Bader
3

In Spyder kann die IPython-Konsole für jede Python-Datei so konfiguriert werden, dass alle Variablen vor jeder Ausführung im Menü gelöscht werden Run -> Configuration -> General settings -> Remove all variables before execution.

Tardis
quelle
2

Die globals()Funktion gibt ein Wörterbuch zurück, in dem Schlüssel Namen von Objekten sind, die Sie benennen können (und Werte sind übrigens ids dieser Objekte). Die exec()Funktion nimmt eine Zeichenfolge und führt sie so aus, als ob Sie sie nur in eine Python-Konsole eingeben. Der Code ist also

for i in list(globals().keys()):
    if(i[0] != '_'):
        exec('del {}'.format(i))
Kolay.Ne
quelle
Während dieses Code-Snippet die Frage möglicherweise löst, hilft eine Erklärung , die Qualität Ihrer Antwort zu verbessern. Denken Sie daran, dass Sie die Frage in Zukunft für Leser beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen.
Stefan Crain
Vielen Dank. Ist es jetzt besser
Kolay.Ne
0

In der IDE im Leerlauf befindet sich Shell / Restart Shell. Cntrl-F6 wird es tun.

Harold Henson
quelle
0

Ist es nicht der einfachste Weg, eine Klasse zu erstellen, die alle benötigten Variablen enthält? Dann haben Sie ein Objekt mit allen aktuellen Variablen, und wenn Sie möchten, können Sie diese Variable überschreiben?

Ivan
quelle