Czy jest sposób na usunięcie utworzonych zmiennych, funkcji itp. Z pamięci interpretera?

114

Od kilku dni szukam dokładnej odpowiedzi na to pytanie, ale nie mam nic dobrego. Nie jestem całkowitym początkującym w programowaniu, ale nie jestem jeszcze na poziomie średniozaawansowanym.

Kiedy jestem w powłoce Pythona, piszę: dir()i widzę wszystkie nazwy wszystkich obiektów w bieżącym zakresie (głównym bloku), jest ich 6:

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

Następnie, kiedy deklaruję zmienną, na przykład x = 10, automatycznie dodaje do listy obiektów pod wbudowanym modułem dir(), a kiedy piszę dir()ponownie, pokazuje teraz:

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

To samo dotyczy funkcji, klas i tak dalej.

Jak usunąć wszystkie te nowe obiekty bez wymazywania standardu 6, który był dostępny na początku?

Czytałem tutaj o „czyszczeniu pamięci”, „czyszczeniu konsoli”, które usuwa cały tekst z okna wiersza poleceń:

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

Ale to wszystko nie ma nic wspólnego z tym, co próbuję osiągnąć, nie usuwa wszystkich używanych obiektów.

funghorn
źródło
2
Dlaczego czujesz, że musisz to zrobić, czy po prostu pytasz z ciekawości?
PM 2Ring
Po prostu nie wiedziałem, że istnieje taka delfunkcja. Zaczynam się uczyć Pythona i często muszę eksperymentować z powłoką, więc standardowe nazwy zmiennych, takie jak xlub yczęsto są już w użyciu, a ponowne uruchomienie powłoki zajmuje kolejne 15 sekund (mam teraz bardzo, bardzo stary laptop). Chciałem więc znaleźć sposób na szybsze wyczyszczenie pamięci Pythona.
funghorn,
1
Ach. FWIW delnie jest dokładnie funkcją, stąd nie (i ). To słowo kluczowe, które wprowadza instrukcję del. Oczywiście, sposób, w jaki faktycznie usuwa obiekt, może wiązać się z funkcjami, ale to już inna historia ...
PM 2Ring
Podczas eksperymentowania z nazwami powłok, takimi jak xlub ynie powinny być używane, chyba że ich używasz. Lub jeśli nie zrobisz czegoś głupiego from _somemodule_ import *, wtedy będziesz miał wszelkiego rodzaju śmieci zaśmiecające to miejsce. :)
PM 2,
1
Przeszukałem drogę do tego pytania i teraz się zastanawiam - dlaczego nie mogę po prostu zrestartować jądra i ponownie uruchomić skryptu od góry, jeśli mimo wszystko chcę usunąć wszystkie zmienne i funkcje?
włóczęga

Odpowiedzi:

159

Możesz usunąć poszczególne nazwy za pomocą del:

del x

lub możesz je usunąć z globals()obiektu:

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

To jest tylko przykładowa pętla; defensywnie usuwa tylko nazwy, które nie zaczynają się od podkreślenia, przyjmując (nie bez powodu), że użyłeś tylko nazw bez podkreślenia na początku w swoim tłumaczu. Zamiast tego możesz użyć zakodowanej na stałe listy nazwisk (umieszczenie na białej liście), jeśli naprawdę chcesz być dokładny. Nie ma wbudowanej funkcji, która mogłaby wykonać czyszczenie za Ciebie, poza wyjściem i ponownym uruchomieniem interpretera.

Zaimportowane moduły ( import os) pozostaną zaimportowane, ponieważ odwołuje się do nich sys.modules; kolejne importy wykorzystają już zaimportowany obiekt modułu. Po prostu nie będziesz mieć do nich odniesienia w swojej obecnej globalnej przestrzeni nazw.

Martijn Pieters
źródło
Cóż, muszę powiedzieć, że startswith('_')wydaje się dość naiwny. Jeśli ktoś jest wystarczająco sprytny, aby pisać, _foo=42a nawet __foo__=42, jak możemy je usunąć? Czy istnieje sposób na programowe uzyskanie nazw standardowych właściwości modułów?
georg
2
@georg: Zakodowałem pętlę defensywnie. Będziesz musiał zakodować początkową listę nazwisk, aby zachować, jeśli chcesz działać lepiej.
Martijn Pieters
Więc nie ma mowy? Myślałem dir(ModuleType()), ale to tylko wraca doci name.
georg
1
@georg: nope; Globalna przestrzeń nazw interpretera również różni się od wydania do wydania, i nie ma niezawodnego sposobu (o którym wiem), aby wyliczyć, co tam było, kiedy otworzyłeś interpreter na późniejszym etapie .
Martijn Pieters
1
Funkcje i klasy @nakE są po prostu obiektami, jak wszystkie inne. Nie są specjalne; użyj białej listy lub sprawdź typ obiektu, którego potrzebujesz, aby zachować klasy i funkcje.
Martijn Pieters
67

Tak. Istnieje prosty sposób na usunięcie wszystkiego w iPythonie. W konsoli iPython wystarczy wpisać:

%reset

Następnie system poprosi o potwierdzenie. Naciśnij y. Jeśli nie chcesz widzieć tego monitu, po prostu wpisz:

%reset -f

To powinno działać ..

EyesBear
źródło
1
Jeszcze raz, dlaczego to nie jest najlepsza odpowiedź?
myradio
12
@myradio Ponieważ nie ma to znaczenia dla wszystkich, którzy nie używają IPythona , i nie odpowiada na pytanie; pytanie dotyczy usuwania globalnych odniesień do obiektów, a nie resetowania zawartości powłoki IPython .
Andreas
17

Możesz użyć garbage collectora w Pythonie:

import gc
gc.collect()
Fardin
źródło
6
Hej @Fardin! dzięki! Twoja odpowiedź zadziałała i uratowała mi dzień! Ale przed gc.collect () zrobiłem del (zmienna).
Gmosy Gnaq
9

Jeśli jesteś w środowisku interaktywnym, takim jak Jupyterlub ipythonmożesz być zainteresowany usuwaniem niechcianych zmiennych, jeśli stają się one ciężkie.

Magiczne polecenia reset i reset_selectivesą dostępne w interaktywnych sesjach Pythona, takich jak ipythoniJupyter

1) reset

reset Resetuje przestrzeń nazw, usuwając wszystkie nazwy zdefiniowane przez użytkownika, jeśli są wywoływane bez argumentów.

ina outparametry określają, czy chcesz opróżnić bufory wejścia / wyjścia. Historia katalogów jest opróżniana z dhistparametrem.

reset in out

Innym interesującym jest to, arrayże usuwa tylko numpy Arrays:

reset array

2) reset_selective

Resetuje przestrzeń nazw, usuwając nazwy zdefiniowane przez użytkownika. Historia wejścia / wyjścia jest pozostawiana na wypadek, gdybyś ich potrzebował.

Przykład czystej tablicy:

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

Źródło: http://ipython.readthedocs.io/en/stable/interactive/magics.html

user1767754
źródło
6

To zadziałało dla mnie.

Musisz uruchomić go dwa razy dla globalnych, a następnie lokalnych

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

for name in dir():
    if not name.startswith('_'):
        del locals()[name]
Viswa
źródło
4

W rzeczywistości Python odzyska pamięć, która nie jest już używana. Nazywa się to zbieraniem śmieci, co jest procesem automatycznym w Pythonie. Ale nadal, jeśli chcesz to zrobić, możesz to usunąć przez del variable_name. Możesz to również zrobić, przypisując zmienną doNone

a = 10
print a 

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

Jedynym sposobem, aby naprawdę odzyskać pamięć z obiektów Pythona, do których nie istnieją odniesienia, jest użycie modułu odśmiecania pamięci. Słowo kluczowe del po prostu odłącza nazwę od obiektu, ale obiekt nadal musi zostać usunięty. Możesz zmusić garbage collectora do uruchomienia przy użyciu modułu gc, ale jest to prawie na pewno przedwczesna optymalizacja, ale ma swoje własne ryzyko. Użycie delnie ma rzeczywistego efektu, ponieważ te nazwy i tak zostałyby usunięte, ponieważ i tak wyszłyby poza zakres.

d-koder
źródło
W rzeczy samej. Oczywiście podczas pracy w globalnej przestrzeni nazw interpretera nazwy nie wykraczają poza zakres, ale co z tego. :) Myślę, że warto też wspomnieć, że to, co dzieje się w pamięci wykorzystywanej przez obiekty, które zostały zebrane śmieci jest zależna od implementacji, ale w większości implementacji Pythona pamięć gc'ed tylko wraca do puli Pythona, to nie powrócił do OS aż do zakończenia programu.
PM 2Ring
@ PM2Ring LOL :) Myślę, że tak. Skąd odwołujesz się do Pythona?
d-coder
2
Zauważ, że w CPythonie GC jest potrzebne tylko do przerwania cykli referencyjnych. Jeśli nie ma żadnych odniesień, obiekt jest natychmiast usuwany z pamięci. Więc del nie mają rzeczywisty wpływ tutaj.
Martijn Pieters
@MartijnPieters, natychmiast usunięto? Czy to termin techniczny? :)
Eryk Sun
2
@eryksun: tak, zgodnie z definicją zawartą w RFC 4042-bis2, oczywiście! :-P
Martijn Pieters