Python >> Tutoriel Python >  >> Python

Comment puis-je libérer explicitement de la mémoire en Python ?

Habituellement, en tant que développeur, vous devez écrire un programme traitant de nombreux documents, traitant d'énormes volumes de données et d'informations et conservant les données en mémoire. Par conséquent, cela conduit à un manque d'espace mémoire qui impacte les performances globales de votre code.

Pour éviter le manque de mémoire, vous devez vider la mémoire en effaçant les données ou les informations qui ne sont plus nécessaires dans le programme. Ce tutoriel vous guidera sur la façon dont la mémoire est allouée et les différentes méthodes pour effacer la mémoire en Python.

Comment la mémoire est-elle allouée en Python ?

En Python, tout est un objet . Ces objets sont stockés dans la mémoire à accéder. Avant que les objets puissent être stockés en mémoire, un bloc de mémoire est initialement alloué. L'allocateur de mémoire de Python s'assure qu'il y a de l'espace disponible pour stocker ces objets. Pour cela, il interagit avec l'administrateur mémoire de votre système d'exploitation.

Python utilise l'allocation de mémoire dynamique . L'un des avantages de ceci est qu'il communique à l'avance la quantité de mémoire dont vous avez besoin pour votre programme. Un autre avantage est que la manipulation de la structure de données est possible car vous pouvez allouer la mémoire selon vos besoins si la structure de données se développe. Cependant, chaque médaille a deux faces. L'allocation dynamique de mémoire continuant tant que le programme est dans l'état d'exécution, elle consomme plus de temps. De même, la mémoire qui a été utilisée doit être libérée après avoir été utilisée pour pallier cet inconvénient.

Garbage Collection en Python

En Python, vous ne pouvez pas explicitement libérer la mémoire. Pour effacer la mémoire, vous devez vous assurer que vous ne continuez pas à stocker les références aux objets. Cela garantira que la mémoire est effacée lorsqu'ils sont ramassés. La récupération de place est effectuée par un programme pour effacer la mémoire précédente d'un objet qui n'est pas utilisé.

Étant donné que les cycles de référence nécessitent un travail de calcul, la récupération de place devrait être automatique. En Python, la récupération de place dépend des allocations et désallocations d'objets. Cela évite de nombreux problèmes liés à la gestion manuelle de l'allocation et de la désallocation de la mémoire. En particulier, Python utilise le comptage de références avec la récupération de place pour nettoyer la mémoire inutilisée.

Maintenant, qu'est-ce que le comptage des références ? ?

 ?Comptage des références

Chaque fois que le développeur crée un objet en Python, l'objet sous-jacent aura à la fois un objet de référence et son type Python comme des listes, un dictionnaire, etc. Lorsque l'objet est référencé dans le programme, son nombre de références est incrémenté et il est décrémenté lorsque un objet est déréférencé. Dans le cas où le compteur de références d'un objet devient 0, la mémoire de l'objet est libérée.

Comment afficher le nombre de références ?

On peut vérifier le nombre de références d'un objet particulier en Python en important le sys module. Vérifiez le nombre de références d'une variable comme indiqué dans l'exemple suivant :

>>> import sys
>>> x = 'hello'
>>> sys.getrefcount(x)

# 2

Remarque : Le nombre de références est deux car nous avons d'abord créé la variable, puis elle est passée à sys.getrefcount() fonction.

Récupération automatique des déchets à l'aide du module gc

Nous pouvons également inspecter le seuil des nouveaux objets (objets en Python appelés objets de génération 0) en chargeant le module gc et demander les seuils de récupération de place :

import gc
print("Garbage collection thresholds: " gc.get_threshold())
Garbage collection thresholds: (500, 10, 10)

Le système ci-dessus a le seuil par défaut de 500. Cela implique que lorsque le nombre d'allocations est supérieur de 500 au nombre de désallocations, le ramasse-miettes automatique commencera à s'exécuter.

Exemple :

import gc
import pprint
import sys
try:
    threshold = int(sys.argv[1])
except (IndexError, ValueError, TypeError):
    print 'Invalid threshold'
    threshold = 5
class MyObj(object):
    def __init__(self, name):
        self.name = name
        print 'Created', self.name
gc.set_debug(gc.DEBUG_STATS)
gc.set_threshold(threshold, 1, 1)
print 'Thresholds:', gc.get_threshold()
print 'Clearing the collector'
gc.collect()
print
print 'Creating objects'
objs = []
for i in range(10):
    objs.append(MyObj(i))

Sortie :

Thresholds: (5, 1, 1)
Clearing the collector
gc: collecting generation 2...
gc: objects in each generation: 218 2683 0
gc: done, 0.0007s elapsed.
Creating objects
gc: collecting generation 0...
gc: objects in each generation: 7 0 2920
gc: done, 0.0000s elapsed.
Created 0
Created 1
Created 2
Created 3
Created 4
gc: collecting generation 0...
gc: objects in each generation: 6 4 2820
gc: done, 0.0000s elapsed.
Created 5
Created 6
Created 7
Created 8
Created 9
gc: collecting generation 2...
gc: objects in each generation: 5 6 2817
gc: done, 0.0005s elapsed.

Remarque : Le ramasse-miettes automatique ne fonctionnera pas si votre appareil manque de mémoire ; au lieu de cela, votre application lèvera des exceptions, qui doivent être prises en charge, ou votre application plantera. De cette manière, toute partie de votre code qui libère un énorme bloc de mémoire a une possibilité décente d'exécuter un ramasse-miettes manuel.

Récupération manuelle de la mémoire à l'aide de gc.collect()

L'application doit être la plus affranchie possible des cycles de référence. L'appel manuel du ramasse-miettes pendant l'exécution du programme est le meilleur moyen de gérer la mémoire consommée par les cycles de référence. Pour invoquer le ramasse-miettes manuellement, vous pouvez utiliser le gc.collect() . Le gc.collect() mehod est utilisé pour renvoyer le nombre d'objets qu'il a collectés et désalloués lors de l'exécution du programme. Nous pouvons invoquer le collecteur de la manière suivante :


importer gc
x =gc.collect()

Exemple :

import gc
import pprint
class Graph(object):
    def __init__(self, name):
        self.name = name
        self.next = None
    def set_next(self, next):
        print('Linking nodes %s.next = %s' % (self, next))
        self.next = next
    def __repr__(self):
        return '%s(%s)' % (self.__class__.__name__, self.name)
# Construct a graph cycle
one = Graph('one')
two = Graph('two')
three = Graph('three')
one.set_next(two)
two.set_next(three)
three.set_next(one)
print()
# Remove references to the graph nodes in this module's namespace
one = two = three = None
# Show the effect of garbage collection
for i in range(2):
    print('Collecting %d ...' % i)
    n = gc.collect()
    print('Unreachable objects:', n)
    print('Remaining Garbage:', end=' ')
    pprint.pprint(gc.garbage)
    print()

Sortie :

Linking nodes Graph(one).next = Graph(two)
Linking nodes Graph(two).next = Graph(three)
Linking nodes Graph(three).next = Graph(one)

Collecting 0 ...
Unreachable objects: 6
Remaining Garbage: []

Collecting 1 ...
Unreachable objects: 0
Remaining Garbage: []

Dans le programme ci-dessus, le cycle est effacé lorsque la récupération de place s'exécute la première fois, car rien ne se réfère aux nœuds Graph en dehors d'eux-mêmes. Le gc.collect() La méthode renvoie le nombre d'objets inaccessibles trouvés.

Veuillez rester à l'écoute et abonnez-vous pour plus de solutions et de discussions intéressantes à l'avenir. Bon apprentissage !