Est-ce que l’interpréteur Python 3 perd de la mémoire lorsqu’il est intégré?

Ce rapport de bogue indique que l’interpréteur Python, à compter de juin 2007, ne nettoiera pas toute la mémoire allouée après avoir appelé Py_Finalize dans une application C / C ++ avec un interpréteur Python incorporé. Il a été recommandé d’appeler Py_Finalize une fois à la fin de l’application.

Ce rapport de bogue indique qu’à partir de la version 3.3 et de mars 2011, l’interpréteur perd encore de la mémoire.

Est-ce que quelqu’un connaît l’état actuel de ce problème? Je suis inquiet parce que j’ai une application dans laquelle l’interpréteur est appelé plusieurs fois par instance en cours d’exécution et que je rencontre des memory leaks.

J’utilise déjà boost :: python pour gérer le nombre de références et j’efface le dictionnaire global de toutes les références créées en exécutant un programme Python entre les exécutions. J’ai quelques classes de singleton – cela pourrait-il être le problème?

Est-ce un problème facile à résoudre ou s’agit-il d’un bogue dans l’interpréteur Python?

Vous pouvez voir que le bogue (le premier, de 2007) est fermé comme “wontfix” par nnorwitz, et que son article est dans le rapport de bogue.

Pourquoi appelez-vous Py_Initialize/Py_Finalize plusieurs fois? Pourquoi ne pas faire quelque chose comme ça (je mélange un peu le C et le Python pour plus de commodité):

 /* startup */ Py_Initialize(); /* do whatever */ while (moreFiles()) { PyRun_SimpleSsortingng("execfile('%s')" % nextFile()); /* do whatever */ } /* shutdown */ Py_Finalize(); 

Le problème est que la plupart des personnes qui écrivent des modules Python ne s’inquiètent pas de ce qui se passe si leur module est finalisé et réinitialisé, et ne se soucient souvent pas de nettoyer lors de la finalisation. Les auteurs de modules savent que toute la mémoire est libérée à la fin du processus et ne se préoccupent pas de plus.

Donc, ce n’est pas vraiment un bogue, c’est vraiment un millier de bogues – un pour chaque module d’extension. C’est un travail énorme pour un bogue qui affecte une minorité d’utilisateurs, dont la plupart disposent d’une solution de contournement viable.

Vous pouvez toujours simplement Py_Finalize l’appel à Py_Finalize , appeler Py_Initialize une seconde fois est un non-op. Cela signifie que votre application utilisera davantage de mémoire lorsque vous exécuterez un script Python pour la première fois. Cette mémoire supplémentaire ne sera pas restituée au système d’exploitation tant que vous ne serez pas fermé. Tant que vous exécutez toujours des scripts Python de temps en temps, je ne le classerai pas comme une fuite. Votre application n’est peut-être pas Valgrind-clean, mais c’est mieux que de couler comme un tamis.

Si vous avez besoin de décharger vos modules (purs) Python pour éviter de perdre de la mémoire, vous pouvez le faire. Supprimez-les sys.modules de sys.modules .

Inconvénients de Py_Finalize : Si vous exécutez des scripts Python à plusieurs resockets, cela n’a pas de sens de lancer Py_Finalize entre eux. Vous devrez recharger tous les modules à chaque réinitialisation. Mon Python charge 28 modules au démarrage.

Commentaire supplémentaire: Le bogue ne se limite pas à Python. Si vous essayez de décharger et de recharger des bibliothèques, une quantité importante de code de bibliothèque dans n’importe quelle langue perdra de la mémoire. Beaucoup de bibliothèques appellent du code C, beaucoup de programmeurs C supposent que leurs bibliothèques sont chargées une fois et déchargées à la fin du processus.