Gibt es eine Möglichkeit, erstellte Variablen, Funktionen usw. aus dem Speicher des Interpreters zu löschen?

113

Ich habe seit ein paar Tagen nach der richtigen Antwort auf diese Frage gesucht, aber nichts Gutes. Ich bin kein Anfänger in der Programmierung, aber noch nicht einmal auf der mittleren Ebene.

Wenn ich in der Shell von Python bin, tippe ich: dir()und ich kann alle Namen aller Objekte im aktuellen Bereich (Hauptblock) sehen, es gibt 6 davon:

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

Wenn ich dann beispielsweise eine Variable deklariere x = 10, wird diese automatisch zu den Objektlisten unter dem integrierten Modul hinzugefügt dir(). Wenn ich dir()erneut tippe, wird jetzt Folgendes angezeigt:

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

Gleiches gilt für Funktionen, Klassen und so weiter.

Wie lösche ich all diese neuen Objekte, ohne den Standard 6 zu löschen, der zu Beginn verfügbar war?

Ich habe hier über "Speicherbereinigung", "Bereinigung der Konsole" gelesen, bei der der gesamte Text aus dem Eingabeaufforderungsfenster gelöscht wird:

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

Aber das alles hat nichts mit dem zu tun, was ich erreichen möchte. Es werden nicht alle verwendeten Objekte entfernt.

Funghorn
quelle
2
Warum hast du das Gefühl, dass du das tun musst, oder fragst du nur aus Neugier?
PM 2Ring
Ich wusste einfach nicht, dass es da draußen eine delFunktion gibt. Ich fange an, Python zu lernen und muss oft in der Shell experimentieren, so dass Standardvariablennamen wie xoder yoft bereits verwendet werden und der Neustart der Shell weitere 15 Sekunden dauert (ich habe jetzt einen sehr, sehr alten Laptop). Deshalb wollte ich einen Weg finden, um den Python-Speicher schneller zu bereinigen.
Funghorn
1
Ah. FWIW delist nicht genau eine Funktion, daher nein (und ). Es ist ein Schlüsselwort, das eine del-Anweisung einführt. Natürlich kann das
Löschen
Beim Experimentieren in der Shell werden Namen wie xoder ysollten nicht verwendet werden, es sei denn, Sie verwenden sie. Oder wenn Sie nicht so etwas Dummes tun from _somemodule_ import *, werden Sie alle Arten von Müll auf dem Platz haben. :)
PM 2Ring
1
Ich habe meinen Weg zu dieser Frage gegoogelt und frage mich jetzt - warum kann ich den Kernel nicht einfach neu starten und das Skript von oben erneut ausführen, wenn ich trotzdem alle Variablen und Funktionen löschen möchte?
Vagabund

Antworten:

158

Sie können einzelne Namen löschen mit del:

del x

oder Sie können sie aus dem globals()Objekt entfernen :

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

Dies ist nur eine Beispielschleife. Es löscht defensiv nur Namen, die nicht mit einem Unterstrich beginnen, und geht davon aus, dass Sie zu Beginn in Ihrem Interpreter nur Namen ohne Unterstrich verwendet haben. Sie können stattdessen eine fest codierte Liste von Namen verwenden (Whitelist), wenn Sie wirklich gründlich sein möchten. Es gibt keine eingebaute Funktion, um das Löschen für Sie durchzuführen, außer nur den Interpreter zu beenden und neu zu starten.

Von Ihnen importierte Module ( import os) bleiben importiert, da auf sie verwiesen wird sys.modules. Nachfolgende Importe verwenden das bereits importierte Modulobjekt wieder. Sie haben in Ihrem aktuellen globalen Namespace einfach keinen Verweis darauf.

Martijn Pieters
quelle
Nun, ich muss sagen, startswith('_')scheint ziemlich naiv. Wenn jemand klug genug ist zu schreiben _foo=42oder sogar __foo__=42, wie können wir diese löschen? Gibt es eine Möglichkeit, die Namen der Standardmoduleigenschaften programmgesteuert abzurufen?
Georg
2
@georg: Ich habe die Schleife defensiv codiert. Sie müssen eine anfängliche Liste von Namen fest codieren, um sie zu behalten, wenn Sie es besser machen möchten.
Martijn Pieters
Also auf keinen Fall? Mein Gedanke war dir(ModuleType()), aber es kehrt nur zurück docund name.
Georg
1
@georg: nein; Der globale Namespace des Interpreters variiert ebenfalls von Release zu Release, und es gibt keine narrensichere Möglichkeit (die ich kenne), aufzuzählen, was sich darin befand, als Sie den Interpreter zu einem späteren Zeitpunkt geöffnet haben .
Martijn Pieters
1
@nakE Funktionen und Klassen sind nur Objekte wie alle anderen. Sie sind nichts Besonderes; Verwenden Sie eine Whitelist oder überprüfen Sie den Objekttyp, den Sie benötigen, um Klassen und Funktionen beizubehalten.
Martijn Pieters
67

Ja. Es gibt eine einfache Möglichkeit, alles in iPython zu entfernen. Geben Sie in der iPython-Konsole einfach Folgendes ein:

%reset

Dann werden Sie vom System zur Bestätigung aufgefordert. Drücken Sie y. Wenn Sie diese Eingabeaufforderung nicht sehen möchten, geben Sie einfach Folgendes ein:

%reset -f

Das sollte funktionieren..

EyesBear
quelle
1
Noch einmal, warum ist dies nicht die beste Antwort?
Myradio
11
@myradio Weil es für alle, die IPython nicht verwenden , irrelevant ist und die Frage auch nicht beantwortet; In der Frage wird gefragt, wie globale Objektreferenzen gelöscht und der Inhalt der IPython- Shell nicht zurückgesetzt werden soll .
Andreas
17

Sie können Python Garbage Collector verwenden:

import gc
gc.collect()
Fardin
quelle
6
Hey @Fardin! Vielen Dank! Ihre Antwort hat den Job gemacht und meinen Tag gerettet! Aber vor gc.collect () habe ich del (Variable) gemacht.
Gmosy Gnaq
9

Wenn Sie sich in einer interaktiven Umgebung wie Jupyteroder befinden ipython, möchten Sie möglicherweise unerwünschte Variablen entfernen, wenn diese schwer werden.

Die Magie befiehlt reset und reset_selectiveist in interaktiven Python-Sitzungen wie ipythonund verfügbar Jupyter

1) reset

reset Setzt den Namespace zurück, indem alle vom Benutzer definierten Namen entfernt werden, wenn sie ohne Argumente aufgerufen werden.

inund die outParameter geben an, ob Sie die In / Out-Caches leeren möchten. Der Verzeichnisverlauf wird mit dem dhistParameter geleert.

reset in out

Ein weiteres interessantes ist, arraydass nur numpy Arrays entfernt werden:

reset array

2) reset_selective

Setzt den Namespace zurück, indem vom Benutzer definierte Namen entfernt werden. Der Eingabe- / Ausgabeverlauf bleibt bei Bedarf erhalten.

Beispiel für ein sauberes Array:

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

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

user1767754
quelle
6

Das hat bei mir funktioniert.

Sie müssen es zweimal für Globals ausführen, gefolgt von Einheimischen

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

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

Tatsächlich stellt Python den Speicher wieder her, der nicht mehr verwendet wird. Dies wird als Garbage Collection bezeichnet, ein automatischer Prozess in Python. Wenn Sie dies dennoch tun möchten, können Sie es mit löschen del variable_name. Sie können dies auch tun, indem Sie die Variable zuweisenNone

a = 10
print a 

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

Die einzige Möglichkeit, Speicher von nicht referenzierten Python-Objekten wirklich zurückzugewinnen, ist der Garbage Collector. Das Schlüsselwort del löst einfach die Bindung eines Namens von einem Objekt, aber das Objekt muss noch durch Müll gesammelt werden. Sie können den Garbage Collector zwingen, mit dem GC-Modul ausgeführt zu werden. Dies ist jedoch mit ziemlicher Sicherheit eine vorzeitige Optimierung, birgt jedoch eigene Risiken. Die Verwendung delhat keine wirklichen Auswirkungen, da diese Namen gelöscht worden wären, da sie ohnehin nicht mehr gültig waren.

D-Codierer
quelle
Tatsächlich. Wenn Sie im globalen Namespace des Interpreters arbeiten, werden die Namen natürlich nicht aus dem Rahmen geraten, aber na und. :) Ich denke, es ist auch erwähnenswert, dass das, was mit dem Speicher passiert, der von Objekten verwendet wird, die durch Müll gesammelt wurden, implementierungsabhängig ist, aber in den meisten Python-Implementierungen geht der gc'ed-Speicher lediglich auf den Python-Pool zurück und wird nicht an den zurückgegeben Betriebssystem, bis das Programm beendet wird.
PM 2Ring
@ PM2Ring LOL :) Ich denke schon. Woher beziehen Sie sich auf Python?
D-Codierer
2
Beachten Sie, dass in CPython der GC nur zum Unterbrechen von Referenzzyklen benötigt wird. Wenn keine Referenzen bleiben, ein Objekt wird aus dem Speicher-insta entfernt. Hat del hier also einen echten Effekt.
Martijn Pieters
@MartijnPieters, insta entfernt? Ist das ein Fachbegriff? :)
Eryk Sun
2
@eryksun: ja, wie in RFC 4042-bis2 definiert, natürlich! :-P
Martijn Pieters