Fuites de mémoire Python

j'ai un script de longue durée qui, s'il fonctionne assez longtemps, consommera toute la mémoire de mon système.

sans entrer dans les détails du script, j'ai deux questions:

  1. y a-t-il des" pratiques exemplaires " à suivre, qui aideront à prévenir les fuites?
  2. Quelles techniques y a-t-il pour déboguer les fuites de mémoire en Python?
124
demandé sur Fragsworth 2009-09-17 00:56:04

9 réponses

Avoir un coup d'oeil à cet article: Traçage python fuites de mémoire

aussi, notez que le " module de collecte des ordures peut en fait avoir des options de débogage activées. Regardez la fonction set_debug . En outre, regardez ce code par Gnibbler pour déterminer les types d'objets qui ont été créés après un appel.

77
répondu ChristopheD 2017-10-08 01:41:11

j'ai essayé la plupart des options mentionnées précédemment, mais j'ai trouvé ce petit paquet intuitif pour être le meilleur: pympler

il est tout à fait simple de tracer des objets qui n'étaient pas ramassés dans les ordures, consultez ce petit exemple:

installer le paquet via pip install pympler

from pympler.tracker import SummaryTracker
tracker = SummaryTracker()

# ... some code you want to investigate ...

tracker.print_diff()

la sortie vous montre tous les objets qui ont été ajoutés, plus la mémoire qu'ils ont consommée.

sortie de L'échantillon:

                                 types |   # objects |   total size
====================================== | =========== | ============
                                  list |        1095 |    160.78 KB
                                   str |        1093 |     66.33 KB
                                   int |         120 |      2.81 KB
                                  dict |           3 |       840 B
      frame (codename: create_summary) |           1 |       560 B
          frame (codename: print_diff) |           1 |       480 B

ce paquet offre un certain nombre d'autres caractéristiques. Vérifier documentation de pympler , en particulier la section identification des fuites de mémoire .

61
répondu linqu 2016-05-20 07:38:37

Laissez-moi vous recommander mem_top outil

qui m'a aidé à résoudre un problème similaire.

il montre instantanément les suspects principaux pour les fuites de mémoire dans un programme Python.

19
répondu Denis Ryzhkov 2014-05-27 07:32:36

Vous devriez spécialement avoir un oeil sur vos données globales ou statiques (longue vie).

lorsque ces données poussent sans restriction, vous pouvez aussi avoir des problèmes en Python.

le collecteur d'ordures ne peut recueillir que des données, qui ne sont plus référencées. Mais vos données statiques peuvent accrocher des éléments de données qui devraient être libérés.

un autre problème peut être les cycles de mémoire, mais au moins en théorie le collecteur d'ordures devrait trouver et éliminer les cycles -- du moins tant qu'ils ne sont pas accrochés à certaines données de longue durée de vie.

quelles sortes de données de longue durée de vie sont particulièrement gênantes? Regardez bien les listes et les dictionnaires -- ils peuvent se développer sans limite. Dans les dictionnaires, vous pourriez même ne pas voir la difficulté à venir depuis lorsque vous accédez à dicts, le nombre de clés dans le dictionnaire peut ne pas être de grande visibilité pour vous ...

9
répondu Juergen 2014-04-08 06:03:33

module Tracemalloc a été intégré comme un module intégré à partir de Python 3.4, et apparemment, il est également disponible pour les versions antérieures de Python comme une bibliothèque tierce partie (ne l'ont pas testé cependant).

ce module est capable de produire les fichiers et les lignes précises qui ont alloué le plus de mémoire. IMHO, cette information est infiniment plus valable que le nombre d'instances allouées pour chaque type (qui se termine jusqu'à être beaucoup de tuples 99% du temps, ce qui est un indice, mais aide à peine dans la plupart des cas).

je vous recommande d'utiliser tracemalloc en association avec pyrasite . 9 fois sur 10, l'exécution du top 10 snippet dans un pyrasite-shell vous donnera assez d'informations et de conseils pour réparer la fuite dans les 10 minutes. Pourtant, si vous êtes toujours incapable de trouver la cause de la fuite, pyrasite-shell en combinaison avec le d'autres outils mentionnés dans ce thread va probablement vous donner quelques conseils en plus. Vous devriez également jeter un oeil à tous les helpers supplémentaires fournis par pyrasite (tels que le visualiseur de mémoire).

6
répondu user1527491 2017-08-16 19:40:05

pas sûr des "meilleures pratiques" pour les fuites de mémoire en python, mais python devrait effacer sa propre mémoire par son collecteur d'ordures. Donc principalement je commencerais par vérifier la liste circulaire de certains courts, puisqu'ils ne seront pas ramassés par le collecteur d'ordures.

4
répondu martiert 2009-09-16 20:59:56

pour détecter et localiser les fuites de mémoire pour les processus de longue durée, p.ex. dans les environnements de production, vous pouvez maintenant utiliser stackimpact . Il utilise tracemalloc en dessous. Plus d'infos dans ce post .

enter image description here

4
répondu logix 2017-07-01 08:05:51

ce n'est pas un conseil exhaustif. Mais une chose à garder à l'esprit en écrivant avec la pensée d'éviter de futures fuites de mémoire (boucles) est de s'assurer que tout ce qui accepte une référence à un rappel, devrait stocker ce rappel comme une référence faible.

3
répondu Dmitry Rubanovich 2012-02-19 20:32:21

en ce qui concerne les meilleures pratiques, gardez un œil sur les fonctions récursives. Dans mon cas, j'ai rencontré des problèmes de récursion (là où il n'y en avait pas besoin). Un exemple simplifié de ce que je faisais:

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    if my_flag:  # restart the function if a certain flag is true
        my_function()

def main():
    my_function()

fonctionne de cette manière récursive ne va pas déclencher la collecte des ordures et éliminer les restes de la fonction, donc à chaque fois à travers l'utilisation de la mémoire est de plus en plus.

Ma solution a été de tirer l'appel récursif de my_function() et main() de la poignée lors de l'appeler à nouveau. de cette façon, la fonction se termine naturellement et nettoie après lui-même.

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    .....
    return my_flag

def main():
    result = my_function()
    if result:
        my_function()
2
répondu The4thIceman 2017-03-03 21:55:14