Gestion de la mémoire [Resolu] - Python - Programmation
Marsh Posté le 19-03-2009 à 13:41:25
Le comportement est tout à fait normal : dans le test 3, tu n'as aucune référence mémorisée vers l'objet rejeté par base.sort(). Quand tu affiches base.sort().tab, Python appelle automatiquement le destructeur vers l'objet rejeté par base.sort() (puisqu'aucune référence n'est faite vers cet objet), et comme ton destructeur supprime l'élément tab de cet objet, par extension, il supprime tout avant que tu l'affiches.
Marsh Posté le 19-03-2009 à 14:39:36
guybrush02 a écrit : Le comportement est tout à fait normal : dans le test 3, tu n'as aucune référence mémorisée vers l'objet rejeté par base.sort(). Quand tu affiches base.sort().tab, Python appelle automatiquement le destructeur vers l'objet rejeté par base.sort() (puisqu'aucune référence n'est faite vers cet objet), et comme ton destructeur supprime l'élément tab de cet objet, par extension, il supprime tout avant que tu l'affiches. |
Yo merci d'avoir répondu si vite. Tu décris effectivement ce dont je me doutais (surtout que je vois le "del" apparaître avant l'affichage du "test3" ). Mais comment faire alors pour
1) rester propre niveau gestion de la mémoire
2) pouvoir récupérer quand-même mon "base.sort().tab"
???
Marsh Posté le 19-03-2009 à 18:01:29
1) Ne pas gérer la mémoire toi-même quand ce n'est pas nécessaire.
2) Respecter le point 1 ^^
Définir un del sur ton objet n'ajoute rien pour le garbage collector, vu que tu ne fais (à peu de choses près) que redéfinir un comportement par défaut (la variation faisant que ça ne marche pas ici). Si tu souhaites libérer de la mémoire, une simple suppression de la variable référençant cet objet est suffisante pour avoir un nettoyage "en cascade" si nécessaire, traité par le garbage collector automatiquement au moment le plus opportun.
Marsh Posté le 19-03-2009 à 18:20:07
guybrush02 a écrit : Définir un del sur ton objet n'ajoute rien pour le garbage collector |
Ca retire des choses même. Ca empêche le détecteur de références circulaires de bosser correctement par exemple, un cycle contenant un objet (ou plus) ayant une méthode __del__ définie ne sera pas détecté, donc pas supprimé, et devra être intégralement nettoyé manuellement.
Il ne faut jamais définir de __del__ quand on est pas certain que c'est exactement ce dont on a besoin (et globalement c'est uniquement le cas pour des ressources rares: handlers de fichiers ou de sockets, connections, ...).
Marsh Posté le 20-03-2009 à 15:12:31
guybrush02 a écrit : 1) Ne pas gérer la mémoire toi-même quand ce n'est pas nécessaire. |
masklinn a écrit : |
Et ce garbage est efficace ? Imaginons que je fasse une boucle style
Code :
|
Sera-ce plus efficace que
Code :
|
???
Marsh Posté le 20-03-2009 à 15:24:19
Sve@r a écrit : Et ce garbage est efficace ? Imaginons que je fasse une boucle style |
Le GC tourne dans les deux cas, il n'y a aucune raison pour qu'il y ait une différence significative, et la 2e version a une instruction (del) de plus que l'autre
Code :
|
Faut arrêter les tentatives de microoptimisation à la con dans ce genre, surtout quand tu ne connais pas le runtime et que tu n'as aucune évidence d'un problème de perf (sans même parler de ne pas savoir où est le problème s'il y en a un)
Marsh Posté le 20-03-2009 à 15:29:04
Et accessoirement, le __del__ qui ne sert à rien a clairement un impact fort sur ce microbench à la con (dans une vraie application il serait probablement invisible) dans la mesure où le runtime doit appeler une fonction Python (alors que la suppression d'origine se fait intégralement en C) et exécuter un slice et deux del à l'intérieur:
Code :
|
(c'est exactement le même code qu'au dessus, j'ai juste rajouté ton __del__ dans la classe)
Marsh Posté le 20-03-2009 à 22:23:05
masklinn a écrit : |
Non tu ne comprends pas. Je ne cherche pas à optimiser, je cherche juste à être certain que tout ce que j'alloue en mémoire est bien libéré une fois que ce n'est plus utile. Je t'ai dit que j'étais issu du C (et aussi du C++). Si je crée une méthode "__del__", je peux contrôler (print) qu'elle est bien appelée lorsque j'appelle mon del <objet>. Si je ne la crée pas, je ne vois rien et ça, ça me gène.
Marsh Posté le 20-03-2009 à 22:31:55
Sve@r a écrit : Non tu ne comprends pas. Je ne cherche pas à optimiser, je cherche juste à être certain que tout ce que j'alloue en mémoire est bien libéré une fois que ce n'est plus utile. Je t'ai dit que j'étais issu du C (et aussi du C++). Si je crée une méthode "__del__", je peux contrôler (print) qu'elle est bien appelée lorsque j'appelle mon del <objet>. Si je ne la crée pas, je ne vois rien et ça, ça me gène. |
Python a un GC, le GC se démerde tout seul, tant que tu n'as pas de problème de mémoire ne te préoccupes pas de ça
Et accessoirement, del ne supprime rien, il décrémente le refcount de l'objet de 1, donc si tu pars avec l'idée que c'est équivalent à free/delete t'as déjà tout faux
Idem pour définir __del__, ça se fait pas dans un langage à GC, sauf si tu as une ressource rare qui doit impérativement être relachée (fichier, connection db) et encore (en 2.5+ on passera par un context manager pour ce genre de trucs)
Marsh Posté le 21-03-2009 à 11:34:49
masklinn a écrit : |
Arf ok
masklinn a écrit : Idem pour définir __del__, ça se fait pas dans un langage à GC, sauf si tu as une ressource rare qui doit impérativement être relachée (fichier, connection db) et encore (en 2.5+ on passera par un context manager pour ce genre de trucs) |
Merci pour tout.
Marsh Posté le 19-03-2009 à 11:59:29
Bonjour à tous - Je viens ici demander une aide suite à un problème qui me turlupine. A force de chercher, j'ai réussi à ramener le problème à un exemple tout simple qui servira de démo facilement compréhensible
Je dois gérer un objet texte. A cet objet y vont s'adjoindre diverses méthodes me permettant de récupérer des infos sur ce texte comme nb lignes, de mots, etc.
A un moment donné, je dois renvoyer un paragraphe du texte. Je me dis en moi-même "un paragraphe étant un mini-texte, si je renvoie une nouvelle instance de mon objet ne contenant que ledit paragraphe, cette instance bénéficiera de toutes les méthodes utiles (nb de lignes, de mots, etc).
Mais c'est là que ça se corse. Voici un petit exemple tout simple montrant le problème. Pour simplifier, j'ai juste créé un objet qui stocke un tableau de nombres et créé une méthode "sort" qui renvoie un nouvel objet contenant le tableau trié
A la base, je crée mon objet. Les affichages sont ok
Au test 1, je récupère une copie triée de mon objet. Aucun souci
Au test 2, j'affiche juste la copie triée de mon objet mais ne l'ai pas sauvegardée. Cependant aucun souci
Au test 3, là j'affiche le tableau stocké dans la copie au moment de la copie et là, je me rends compte que le destructeur a déjà fait son office et le tableau est vide.
Ce qui est intéressant, c'est que si dans le destructeur on supprime le nettoyage du tableau (del self.tab[:]), là tout marche bien. Je sais que Python possède une gestion de la mémoire et que je ne devrais pas me préoccuper de libération de mon tableau interne mais je suis issu du C et c'est plus fort que moi. Si mon constructeur crée un élément, mon destructeur supprime l'élément.
Quelqu'un aurait un conseil à me donner ?
Merci
Message édité par Sve@r le 21-03-2009 à 11:35:23
---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.