web-dev-qa-db-fra.com

Python fuites de mémoire

J'ai un script long qui, s'il est laissé assez long, consomme toute la mémoire de mon système.

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

  1. Existe-t-il des "meilleures pratiques" à suivre pour éviter les fuites?
  2. Quelles techniques existe-t-il pour déboguer les fuites de mémoire en Python?
157
Fragsworth

Jetez un coup d'œil à cet article: Traçage python fuites de mémoire

Notez également que le module de récupération de place peut en fait définir des indicateurs de débogage. Regarde le set_debug une fonction. De plus, regardez ce code de Gnibbler pour déterminer les types d’objets créés après un appel.

96
ChristopheD

J’ai essayé la plupart des options mentionnées précédemment, mais j’ai trouvé que ce petit paquet intuitif était le meilleur: pympler

C'est assez simple de tracer des objets qui n'ont pas été ramassés. Cochez 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 utilisée.

Exemple de sortie:

                                 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 fournit un certain nombre de fonctionnalités supplémentaires. Vérifiez documentation de pympler , en particulier la section Identification des fuites de mémoire .

76
linqu

Me laisser recommander mem_top outil,
qui m'a aidé à résoudre un problème similaire.

Il montre juste instantanément les principaux suspects de fuite de mémoire dans un programme Python.

22
Denis Ryzhkov

module Tracemalloc a été intégré en tant que module intégré à partir de Python 3.4, et apparemment, il est également disponible pour les versions antérieures de Python = as ne bibliothèque tierce (je ne l’ai pas encore testé).

Ce module est capable de sortir les fichiers et les lignes qui ont alloué le plus de mémoire. IMHO, cette information est infiniment plus précieuse que le nombre d'instances allouées pour chaque type (ce qui finit par représenter 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 combinaison avec pyrasite . 9 fois sur 10, exécuter le extrait du top 1 dans un pyrasite-Shell vous donnera suffisamment d'informations et de conseils pour réparer la fuite dans les 10 minutes. Cependant, si vous ne parvenez toujours pas à trouver la cause de la fuite, pyrasite-Shell, en combinaison avec les autres outils mentionnés dans ce fil de discussion, vous donnera probablement encore plus d'indices. Vous devriez également jeter un coup d'œil sur toutes les aides supplémentaires fournies par pyrasite (comme le visualiseur de mémoire).

13
user1527491

Vous devriez spécialement examiner vos données globales ou statiques (données durables).

Lorsque ces données augmentent sans restriction, vous pouvez également rencontrer des problèmes en Python.

Le garbage collector peut uniquement collecter des données, qui ne sont plus référencées. Mais vos données statiques peuvent associer des éléments de données à libérer.

Un autre problème peut être les cycles de mémoire, mais au moins en théorie, le ramasse-miettes doit rechercher et éliminer les cycles, du moins tant qu'ils ne sont pas accrochés à des données à vie longue.

Quels types de données de longue durée de vie sont particulièrement gênants? Regardez bien les listes et les dictionnaires - ils peuvent évoluer sans limite. Dans les dictionnaires, vous ne verrez peut-être même pas le problème, car lorsque vous accédez à des dict, le nombre de clés dans le dictionnaire peut ne pas être très visible pour vous ...

11
Juergen

Pour détecter et localiser des fuites de mémoire pour des processus longs, par ex. dans les environnements de production, vous pouvez maintenant utiliser stackimpact . Il utilise tracemalloc dessous. Plus d'infos dans this post .

enter image description here

7
logix

Pas sûr des "meilleures pratiques" pour les fuites de mémoire en python, mais python devrait effacer sa propre mémoire par son garbage collector. Donc, je commencerais tout d'abord par vérifier la liste circulaire de quelques-uns, ne sera pas ramassé par le ramasse-miettes.

4
martiert

En ce qui concerne les meilleures pratiques, gardez un œil sur les fonctions récursives. Dans mon cas, j'ai rencontré des problèmes avec la récursivité (où il n'y avait pas besoin d'être). 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()

fonctionner de manière récursive ne déclenchera pas la récupération de place et effacera les restes de la fonction, de sorte que l'utilisation de la mémoire augmente chaque fois.

Ma solution consistait à extraire l'appel récursif de my_function () et à permettre à main () de savoir quand l'appeler à nouveau. De cette façon, la fonction se termine naturellement et se nettoie après elle-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()
3
The4thIceman

Ce n'est en aucun cas un conseil exhaustif. Mais la première chose à garder à l’esprit lorsque vous écrivez avec l’idée d’éviter les fuites de mémoire (boucles) est de vous assurer que tout ce qui accepte une référence à un rappel doit le stocker comme une référence faible.

3
Dmitry Rubanovich