Esiste un modo per eliminare le variabili, le funzioni, ecc. Create dalla memoria dell'interprete?


114

Sono un paio di giorni che cerco la risposta precisa a questa domanda, ma non ho niente di buono. Non sono un principiante assoluto nella programmazione, ma non ancora nemmeno a livello intermedio.

Quando sono nella shell di Python, digito: dir()e posso vedere tutti i nomi di tutti gli oggetti nello scope corrente (blocco principale), ce ne sono 6:

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

Quindi, quando dichiaro una variabile, ad esempio x = 10, si aggiunge automaticamente a quegli elenchi di oggetti nel modulo integrato dir()e quando digito di dir()nuovo, ora viene visualizzato:

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

Lo stesso vale per funzioni, classi e così via.

Come cancello tutti quei nuovi oggetti senza cancellare lo standard 6 che era disponibile all'inizio?

Ho letto qui di "pulizia della memoria", "pulizia della console", che cancella tutto il testo dalla finestra del prompt dei comandi:

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

Ma tutto questo non ha nulla a che fare con quello che sto cercando di ottenere, non pulisce tutti gli oggetti usati.


2
Perché senti di doverlo fare o lo stai chiedendo solo per curiosità?
PM 2 Ring

Semplicemente non sapevo che ci fosse una delfunzione là fuori. Sto iniziando a imparare Python e spesso devo sperimentare nella shell, quindi i nomi di variabili standard come xo ysono spesso già in uso e il riavvio della shell richiede altri 15 secondi (ora ho un laptop molto, molto vecchio). Quindi volevo trovare un modo per pulire la memoria Python più velocemente.
funghorn

1
Ah. FWIW, delnon è esattamente una funzione, quindi no (e ). È una parola chiave che introduce un'istruzione del. Ovviamente, il modo in cui elimina effettivamente un oggetto può implicare funzioni, ma questa è un'altra storia ...
PM 2 Ring

Quando si sperimenta nella shell nomi come xo ynon dovrebbero essere in uso a meno che non li si stia utilizzando. Oppure, a meno che tu non faccia qualcosa di sciocco come from _somemodule_ import *, allora avrai tutti i tipi di spazzatura che ingombrano il posto. :)
PM 2 Ring

1
Ho cercato su Google questa domanda e ora mi chiedo: perché non posso semplicemente riavviare il kernel e rieseguire lo script dall'alto se voglio comunque eliminare tutte le variabili e le funzioni?
vagabondo

Risposte:


159

Puoi eliminare singoli nomi con del:

del x

oppure puoi rimuoverli globals()dall'oggetto:

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

Questo è solo un esempio di ciclo; in modo difensivo elimina solo i nomi che non iniziano con un carattere di sottolineatura, facendo un presupposto (non irragionevole) che hai usato solo nomi senza un carattere di sottolineatura all'inizio nel tuo interprete. È possibile utilizzare un elenco di nomi hardcoded da mantenere invece (whitelisting) se si desidera davvero essere accurati. Non esiste una funzione incorporata per eseguire la cancellazione per te, a parte uscire e riavviare l'interprete.

I moduli che hai importato ( import os) rimarranno importati perché sono referenziati da sys.modules; le importazioni successive riutilizzeranno l'oggetto modulo già importato. Semplicemente non avrai un riferimento a loro nel tuo attuale spazio dei nomi globale.


Beh, devo dire che startswith('_')sembra abbastanza ingenuo. Se qualcuno è abbastanza intelligente da scrivere _foo=42o addirittura __foo__=42, come possiamo eliminarli? C'è un modo per ottenere i nomi delle proprietà dei moduli standard a livello di codice?
georg

2
@georg: ho codificato il ciclo in modo difensivo. Dovrai codificare un elenco iniziale di nomi da mantenere se vuoi fare di meglio.
Martijn Pieters

Quindi no? Il mio pensiero era dir(ModuleType()), ma ritorna solo doce name.
georg

1
@georg: no; lo spazio dei nomi globale dell'interprete varia da versione a versione e non esiste un modo infallibile (che io sappia) per enumerare cosa c'era dentro quando hai aperto l'interprete in una fase successiva .
Martijn Pieters

1
Le funzioni e le classi @nakE sono solo oggetti come gli altri. Non sono speciali; utilizzare una whitelist o verificare il tipo di oggetto necessario per preservare classi e funzioni.
Martijn Pieters

67

Sì. C'è un modo semplice per rimuovere tutto in iPython. Nella console iPython, digita semplicemente:

%reset

Quindi il sistema ti chiederà di confermare. Premi y. Se non vuoi vedere questo messaggio, digita semplicemente:

%reset -f

Questo dovrebbe funzionare ..


1
Ancora una volta, perché questa non è la risposta migliore?
myradio

11
@myradio Perché è irrilevante per tutti coloro che non usano IPython e non risponde nemmeno alla domanda; la domanda chiede come eliminare i riferimenti agli oggetti globali, non ripristinare il contenuto della shell IPython .
Andreas

17

Puoi usare Python Garbage Collector:

import gc
gc.collect()

6
Hey @Fardin! Grazie! La tua risposta ha funzionato e mi ha salvato la giornata! Ma prima di gc.collect () ho fatto del (variable).
Gmosy Gnaq

9

Se ti trovi in ​​un ambiente interattivo come Jupytero ipythonpotresti essere interessato a cancellare le var indesiderate se stanno diventando pesanti.

I comandi magici reset ed reset_selectiveè disponibile su sessioni interattive di Python come ipythoneJupyter

1) reset

reset Reimposta lo spazio dei nomi rimuovendo tutti i nomi definiti dall'utente, se chiamati senza argomenti.

inei outparametri specificano se si desidera svuotare le cache in / out. La cronologia della directory viene cancellata con il dhistparametro.

reset in out

Un altro interessante è arrayche rimuove solo numpy Arrays:

reset array

2) reset_selective

Reimposta lo spazio dei nomi rimuovendo i nomi definiti dall'utente. La cronologia di input / output viene lasciata in giro nel caso in cui ne avessi bisogno.

Esempio di array pulito:

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

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


6

Questo ha funzionato per me.

È necessario eseguirlo due volte una volta per le globali seguite da quelle locali

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

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

4

In realtà python recupererà la memoria che non è più in uso, questo è chiamato garbage collection che è un processo automatico in python. Ma comunque, se vuoi farlo, puoi eliminarlo del variable_name. Puoi farlo anche assegnando la variabile aNone

a = 10
print a 

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

L'unico modo per recuperare veramente la memoria da oggetti Python non referenziati è tramite il garbage collector. La parola chiave del svincola semplicemente un nome da un oggetto, ma l'oggetto deve ancora essere sottoposto a garbage collection. È possibile forzare l'esecuzione di Garbage Collector utilizzando il modulo gc, ma questa è quasi certamente un'ottimizzazione prematura ma ha i suoi rischi. L'utilizzo delnon ha alcun effetto reale, dal momento che quei nomi sarebbero stati cancellati in quanto uscivano comunque dall'ambito.


Infatti. Ovviamente, quando si lavora nei nomi degli spazi dei nomi globali dell'interprete non usciranno dall'ambito, ma allora. :) Immagino che valga anche la pena ricordare che ciò che accade alla memoria utilizzata dagli oggetti che sono stati raccolti in modo indesiderato dipende dall'implementazione, ma nella maggior parte delle implementazioni Python la memoria gc'ed torna semplicemente al pool Python, non viene restituita al OS fino alla chiusura del programma.
PM 2 Ring

@ PM2Ring LOL :) Penso di sì. Da dove ti riferisci per Python?
d-coder

2
Si noti che in CPython il GC è necessario solo per interrompere i cicli di riferimento. Se non rimangono riferimenti, un oggetto viene rimosso dalla memoria. Quindi del non avere un effetto reale qui.
Martijn Pieters

@MartijnPieters, insta-removed? È un termine tecnico? :)
Eryk Sun

2
@eryksun: sì, come definito dalla RFC 4042-bis2, ovviamente! :-P
Martijn Pieters
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.