Existe-t-il un moyen de supprimer les variables créées, les fonctions, etc. de la mémoire de l'interpréteur?

114

Je cherche la réponse exacte à cette question depuis quelques jours maintenant, mais je n'ai rien de bon. Je ne suis pas un débutant complet en programmation, mais pas encore au niveau intermédiaire.

Quand je suis dans le shell de Python, je tape: dir()et je peux voir tous les noms de tous les objets dans la portée actuelle (bloc principal), il y en a 6:

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

Ensuite, lorsque je déclare une variable, par exemple x = 10, elle ajoute automatiquement à cette liste d'objets sous le module intégré dir(), et lorsque je tape à dir()nouveau, cela montre maintenant:

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

Il en va de même pour les fonctions, les classes, etc.

Comment supprimer tous ces nouveaux objets sans effacer le standard 6 qui était disponible au début?

J'ai lu ici à propos du "nettoyage de la mémoire", du "nettoyage de la console", qui efface tout le texte de la fenêtre d'invite de commande:

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

Mais tout cela n'a rien à voir avec ce que j'essaie de réaliser, cela ne nettoie pas tous les objets utilisés.

funghorn
la source
2
Pourquoi pensez-vous que vous devez faire cela, ou demandez-vous simplement par curiosité?
PM 2 Ring
Je ne savais tout simplement pas qu'il y avait une delfonction là-bas. Je commence à apprendre Python et je dois souvent expérimenter dans le shell, donc les noms de variables standard comme xou ysont souvent déjà utilisés et le redémarrage du shell prend encore 15 secondes à faire (j'ai un très, très vieux portable maintenant). Je voulais donc trouver un moyen de nettoyer plus rapidement la mémoire Python.
funghorn
1
Ah. FWIW, deln'est pas exactement une fonction, donc non (et ). C'est un mot-clé qui introduit une instruction del. Bien sûr, la façon dont il supprime réellement un objet peut impliquer des fonctions, mais c'est une autre histoire ...
PM 2 Ring
Lors de l'expérimentation dans les noms de shell comme xou yne devraient pas être utilisés à moins que vous ne les utilisiez. Ou à moins que vous ne fassiez quelque chose de stupide from _somemodule_ import *, alors vous obtiendrez toutes sortes de déchets encombrant l'endroit. :)
PM 2Ring
1
J'ai cherché sur Google cette question et maintenant je me demande - pourquoi ne puis-je pas simplement redémarrer le noyau et relancer le script par le haut si je veux quand même supprimer toutes les variables et fonctions?
vagabond

Réponses:

159

Vous pouvez supprimer des noms individuels avec del:

del x

ou vous pouvez les supprimer de l' globals()objet:

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

Ceci est juste un exemple de boucle; il supprime de manière défensive uniquement les noms qui ne commencent pas par un trait de soulignement, faisant l'hypothèse (non déraisonnable) que vous n'avez utilisé que des noms sans trait de soulignement au début dans votre interpréteur. Vous pouvez utiliser une liste de noms codée en dur à conserver à la place (liste blanche) si vous voulez vraiment être minutieux. Il n'y a pas de fonction intégrée pour faire l'effacement à votre place, à part simplement quitter et redémarrer l'interpréteur.

Les modules que vous avez importés ( import os) resteront importés car ils sont référencés par sys.modules; les importations suivantes réutiliseront l'objet de module déjà importé. Vous n'aurez tout simplement pas de référence à eux dans votre espace de noms global actuel.

Martijn Pieters
la source
Eh bien, je dois dire que cela startswith('_')semble assez naïf. Si quelqu'un est assez intelligent pour écrire _foo=42ou même __foo__=42, comment pouvons-nous les supprimer? Existe-t-il un moyen d'obtenir les noms des propriétés de module standard par programme?
georg
2
@georg: J'ai codé la boucle de manière défensive. Vous devrez coder en dur une liste initiale de noms à conserver si vous voulez faire mieux.
Martijn Pieters
Alors, pas question? Ma pensée était dir(ModuleType()), mais il ne fait que revenir docet name.
georg
1
@georg: non; l'espace de noms global de l'interpréteur varie également d'une version à l'autre, et il n'y a pas de moyen infaillible (à ma connaissance) d'énumérer ce qu'il y avait là-dedans lorsque vous avez ouvert l'interpréteur à un stade ultérieur .
Martijn Pieters
1
Les fonctions et classes @nakE ne sont que des objets comme les autres. Ils ne sont pas spéciaux; utilisez une liste blanche ou vérifiez le type d'objet dont vous avez besoin pour conserver les classes et les fonctions.
Martijn Pieters
67

Oui. Il existe un moyen simple de tout supprimer dans iPython. Dans la console iPython, tapez simplement:

%reset

Ensuite, le système vous demandera de confirmer. Appuyez sur y. Si vous ne souhaitez pas voir cette invite, tapez simplement:

%reset -f

Cela devrait fonctionner.

YeuxOurs
la source
1
Encore une fois, pourquoi celle-ci n'est-elle pas la meilleure réponse?
myradio
12
@myradio Parce que ce n'est pas pertinent pour tout le monde qui n'utilise pas IPython , et qu'il ne répond pas non plus à la question; la question demande comment supprimer les références d'objets globales, pas réinitialiser le contenu du shell IPython .
Andreas
17

Vous pouvez utiliser le garbage collector python:

import gc
gc.collect()
Fardin
la source
6
Salut @Fardin! Merci! Votre réponse a fait le travail et m'a sauvé la journée! Mais avant gc.collect (), j'ai fait del (variable).
Gmosy Gnaq
9

Si vous êtes dans un environnement interactif comme Jupyterou ipythonvous pourriez être intéressé par la suppression des variables indésirables si elles deviennent lourdes.

Les commandes magiques reset et reset_selectivesont disponibles sur les sessions python interactives comme ipythonetJupyter

1) reset

reset Réinitialise l'espace de noms en supprimant tous les noms définis par l'utilisateur, s'ils sont appelés sans arguments.

inet les outparamètres spécifient si vous souhaitez vider les caches d'entrée / sortie. L'historique du répertoire est vidé avec le dhistparamètre.

reset in out

Un autre intéressant est arrayque ne supprime que les tableaux numpy:

reset array

2) reset_selective

Réinitialise l'espace de noms en supprimant les noms définis par l'utilisateur. L'historique des entrées / sorties est conservé au cas où vous en auriez besoin.

Exemple de réseau propre:

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

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

user1767754
la source
6

Cela a fonctionné pour moi.

Vous devez l'exécuter deux fois pour les globaux suivis des locaux

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

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

En fait, python récupérera la mémoire qui n'est plus utilisée. C'est ce qu'on appelle le garbage collection qui est un processus automatique en python. Mais toujours si vous voulez le faire, vous pouvez le supprimer par del variable_name. Vous pouvez également le faire en affectant la variable àNone

a = 10
print a 

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

La seule façon de vraiment récupérer de la mémoire à partir d'objets Python non référencés est via le garbage collector. Le mot-clé del dissocie simplement un nom d'un objet, mais l'objet doit toujours être récupéré. Vous pouvez forcer le garbage collector à s'exécuter à l'aide du module gc, mais il s'agit presque certainement d'une optimisation prématurée, mais elle comporte ses propres risques. L'utilisation deln'a aucun effet réel, puisque ces noms auraient été supprimés car ils étaient de toute façon hors de portée.

d-coder
la source
En effet. Bien sûr, lorsque vous travaillez dans les noms d'espaces de noms globaux de l'interpréteur, ils ne sortent pas de leur portée, mais tant pis. :) Je suppose que cela vaut également la peine de mentionner que ce qui arrive à la mémoire utilisée par les objets qui ont été récupérés dépend de l'implémentation, mais dans la plupart des implémentations Python, la mémoire gc'ed retourne simplement au pool Python, elle n'est pas retournée au OS jusqu'à ce que le programme se termine.
PM 2 Ring
@ PM2Ring LOL :) Je pense que oui. D'où vous référez-vous pour python?
d-coder
2
Notez qu'en CPython, le GC n'est nécessaire que pour interrompre les cycles de référence. S'il ne reste aucune référence, un objet est insta-supprimé de la mémoire. Cela a del donc un effet réel ici.
Martijn Pieters
@MartijnPieters, supprimé insta? Est-ce un terme technique? :)
Eryk Sun
2
@eryksun: oui, comme défini par RFC 4042-bis2, bien sûr! :-P
Martijn Pieters