Je vous recommande d'utiliser la méthode Python with
déclaration pour la gestion des ressources qui doivent être nettoyées. Le problème de l'utilisation d'une déclaration explicite close()
est que vous devez vous inquiéter du fait que les gens oublient de l'appeler ou de le placer dans un fichier de type finally
pour éviter une fuite de ressources lorsqu'une exception se produit.
Pour utiliser le with
créez une classe avec les méthodes suivantes :
def __enter__(self)
def __exit__(self, exc_type, exc_value, traceback)
Dans votre exemple ci-dessus, vous utiliseriez
class Package:
def __init__(self):
self.files = []
def __enter__(self):
return self
# ...
def __exit__(self, exc_type, exc_value, traceback):
for file in self.files:
os.unlink(file)
Ensuite, quand quelqu'un veut utiliser votre classe, il fait ce qui suit :
with Package() as package_obj:
# use package_obj
La variable package_obj sera une instance de type Package (c'est la valeur renvoyée par la fonction __enter__
méthode). Son site __exit__
sera automatiquement appelée, qu'une exception se produise ou non.
Vous pouvez même pousser cette approche un peu plus loin. Dans l'exemple ci-dessus, quelqu'un pourrait toujours instancier Package à l'aide de son constructeur sans utiliser l'attribut with
clause. Vous ne voulez pas que cela se produise. Vous pouvez remédier à ce problème en créant une classe PackageResource qui définit l'attribut __enter__
y __exit__
méthodes. Ensuite, la classe Package serait définie strictement à l'intérieur de la classe __enter__
et retourné. De cette façon, l'appelant ne pourra jamais instancier la classe Package sans utiliser une méthode de type with
déclaration :
class PackageResource:
def __enter__(self):
class Package:
...
self.package_obj = Package()
return self.package_obj
def __exit__(self, exc_type, exc_value, traceback):
self.package_obj.cleanup()
Vous l'utiliserez comme suit :
with PackageResource() as package_obj:
# use package_obj
3 votes
En lisant ce que vous avez lié, les variables globales qui disparaissent ne semblent pas s'appliquer ici, à moins que vous ne parliez de la sortie du programme, pendant laquelle, selon ce que vous avez lié, il est POSSIBLE que le module os lui-même ait déjà disparu. Sinon, je ne pense pas que cela s'applique aux variables membres dans une méthode __del__().
3 votes
L'exception est levée bien avant que mon programme ne se termine. L'exception AttributeError que je reçois est due au fait que Python dit qu'il ne reconnaît pas self.files comme étant un attribut de Package. Il se peut que je me trompe, mais si par "globales", on n'entend pas les variables globales aux méthodes (mais peut-être locales à la classe), alors je ne sais pas ce qui cause cette exception. Google hints Python se réserve le droit de nettoyer les données des membres avant que __del__(self) ne soit appelé.
1 votes
Le code tel que posté semble fonctionner pour moi (avec Python 2.5). Pouvez-vous poster le code qui ne fonctionne pas - ou une version simplifiée (plus c'est simple, mieux c'est) qui provoque toujours l'erreur ?
0 votes
@ wilhelmtell pouvez-vous donner un exemple plus concret ? Dans tous mes tests, le del destructeur fonctionne parfaitement.
0 votes
La classe n'est pas très différente de celle que j'ai postée, mais elle est utilisée dans un morceau de code beaucoup plus important qui est trop grand pour que ces marges puissent le contenir... Je vais essayer de trouver le plus petit code qui déclenche cela.
0 votes
Wilhelmtell vérifiez ma dernière mise à jour
10 votes
Si quelqu'un veut savoir : Cet article explique pourquoi
__del__
ne doit pas être utilisé comme la contrepartie de__init__
. (c'est-à-dire qu'il ne s'agit pas d'un "destructeur" au sens où l'on parle de__init__
est un constructeur.0 votes
BOTTAL LINE : python ne supporte pas RAII comme C++ et d'autres langages (aka LIFO object destruction). RÉFÉRENCES : documentation python , PEP 343 , wikibooks for Python "Python ne prend pas en charge le RAII". .
0 votes
@franklin Le seul argument de l'article est de s'assurer que
__init__
réussit. Si ce n'est pas le cas, je considérerais cela comme un bogue. Pour être honnête, je ne vois pas d'argument majeur.