178 votes

La clôture explicite des dossiers est-elle importante ?

En Python, si vous ouvrez un fichier sans appeler close() ou fermer le fichier mais sans utiliser try - finally ou le " with "Cela pose-t-il un problème ? Ou est-il suffisant, en tant que pratique de codage, de s'appuyer sur le ramasse-miettes de Python pour fermer tous les fichiers ? Par exemple, si l'on fait ceci :

for line in open("filename"):
    # ... do stuff ...

... est-ce un problème parce que le fichier ne peut jamais être fermé et qu'une exception peut se produire qui l'empêche d'être fermé ? Ou bien le fichier sera-t-il définitivement fermé à la fin de l'opération for parce que le fichier sort du champ d'application ?

18 votes

Le fichier fait no sortent du champ d'application à la fin de la for bloc. Son nombre de références passera à zéro, ce qui entraînera sa fermeture automatique, mais seules les fonctions, les classes et les modules définissent des portées en Python, et non d'autres instructions composées.

26 votes

Ce n'est pas un problème tant que ce n'est pas un problème. Au niveau du système d'exploitation, tous les fichiers ouverts par le script seront fermés lorsque le script sortira, vous n'avez donc pas à vous soucier de la fermeture des fichiers dans les script de l'outil jetable. Cependant, les processus ont une limite sur le nombre de fichiers ouverts qu'ils peuvent maintenir, donc les script complexes ou de longue durée doivent être plus prudents. Dans tous les cas, c'est une bonne habitude de fermer vos fichiers.

3 votes

@agf : Vous avez raison de dire que le fichier ne sort pas du champ d'application, mais ce n'est pas lié à la distinction entre for et les fonctions/classes/modules. C'est beaucoup plus simple que cela : les objets n'ont pas de portée, seuls les noms en ont une. Il n'y a pas de nom qui se réfère à cet objet, donc il n'y a rien ici qui reste dans la portée ou qui en sorte.

151voto

Peter Graham Points 2630

Dans votre exemple, la fermeture du fichier n'est pas garantie avant la sortie de l'interpréteur. Dans les versions actuelles de CPython, le fichier sera fermé à la fin de la boucle for, car CPython utilise le comptage de références comme principal mécanisme de ramassage des ordures, mais il s'agit d'un détail d'implémentation, et non d'une caractéristique du langage. D'autres implémentations de Python ne sont pas garanties de fonctionner de cette manière. Par exemple, IronPython, PyPy et Jython n'utilisent pas le comptage de références et ne fermeront donc pas le fichier à la fin de la boucle.

C'est une mauvaise pratique que de s'appuyer sur l'implémentation du garbage collection de CPython, car cela rend votre code moins portable. Il se peut que vous n'ayez pas de fuites de ressources si vous utilisez CPython, mais si vous passez à une implémentation de Python qui n'utilise pas le comptage de références, vous devrez revoir tout votre code et vous assurer que tous vos fichiers sont fermés correctement.

Pour votre exemple, utilisez :

with open("filename") as f:
     for line in f:
        # ... do stuff ...

9 votes

L'utilisation de with open() as f fermer automatiquement le fichier une fois qu'il est terminé ?

29 votes

@Rohan oui, c'est la petite magie que l'on retrouve dans le système. with mais bien sûr, pour que cette magie opère, l'objet doit posséder les méthodes spéciales __enter__ y __exit__ Dans ce dernier cas, l'objet fait l'objet d'une close et toute autre opération de nettoyage à effectuer à la fin de l'opération. with déclaration...

4 votes

Pour information : cette réponse explique seulement "quand il serait fermé" mais n'explique pas "que se passerait-il s'il restait ouvert". Pour ce dernier point, veuillez lire la partie "Que se passe-t-il si un fichier reste ouvert ?" de cette réponse ( askubuntu.com/questions/701491/ )

28voto

Ethan Furman Points 12683

Certains Python ferment automatiquement les fichiers lorsqu'ils ne sont plus référencés, tandis que d'autres ne le font pas et c'est au système d'exploitation de fermer les fichiers lorsque l'interpréteur Python quitte le système.

Même pour les Pythons qui ferment des fichiers pour vous, le moment n'est pas garanti : ce peut être immédiatement, ou quelques secondes/minutes/heures/jours plus tard.

Ainsi, même si vous ne rencontrez pas de problèmes avec le Python que vous utilisez, ce n'est certainement pas une bonne pratique que de laisser vos fichiers ouverts. En fait, dans cpython 3, vous recevrez désormais des avertissements indiquant que le système a dû fermer des fichiers pour vous si vous ne l'avez pas fait.

Moralité : nettoyez derrière vous :)

10 votes

Les fichiers sont fermés lorsqu'ils ne sont plus référencés dans CPython, mais ce n'est pas une fonctionnalité du langage. Si c'était le cas, vous pourriez très bien vous y fier.

12voto

qarma Points 3310

Bien qu'il soit tout à fait sûr d'utiliser une telle construction dans ce cas particulier, il y a quelques mises en garde à propos de la généralisation d'une telle pratique :

  • run peut potentiellement être à court de descripteurs de fichiers, bien que cela soit peu probable, imaginez que vous soyez à la recherche d'un bogue de ce type.
  • il se peut que vous ne puissiez pas supprimer ledit fichier sur certains systèmes, par exemple win32
  • si vous utilisez autre chose que CPython, vous ne savez pas quand le fichier est fermé pour vous
  • si vous ouvrez le fichier en mode écriture ou lecture-écriture, vous ne savez pas quand les données sont effacées

3voto

Nam Nguyen Points 1341

Le fichier est collecté et donc fermé. C'est le GC qui détermine quand il est fermé, pas vous. Il est évident que cette pratique n'est pas recommandée, car vous risquez d'atteindre la limite des gestionnaires de fichiers ouverts si vous ne fermez pas les fichiers dès que vous avez fini de les utiliser. Que se passe-t-il si, à l'intérieur de ce for de votre boucle, vous ouvrez plus de fichiers et les laissez traîner ?

0 votes

Mais si vous ouvrez d'autres fichiers dans cette boucle for, il y aura toujours plus d'un fichier ouvert simultanément, que vous fermiez explicitement l'un d'entre eux ou non. Êtes-vous en train de dire que le fichier n'est pas nécessairement ramassé dès qu'il sort du champ d'application, et qu'il serait donc fermé plus tôt si cela était fait explicitement ? Qu'en est-il lorsqu'une exception se produit (lorsque vous utilisez with/try-finally par rapport à ne pas le faire) ?

1 votes

Dans CPython, le comptage des références fait que le fichier est collecté après le fichier for vous n'aurez pas à attendre la prochaine opération de ramassage des ordures.

3voto

zps215 Points 51

Bonjour Il est très important de fermer votre descripteur de fichier dans le cas où vous allez utiliser son contenu dans le même script python. Je m'en suis rendu compte aujourd'hui après de longues heures de débogage. La raison est que le contenu ne sera édité/supprimé/enregistré qu'après avoir fermé le descripteur de fichier et que les modifications seront affectées au fichier !

Supposons donc que vous écriviez le contenu d'un nouveau fichier et que, sans fermer fd, vous utilisiez ce fichier (et non fd) dans une autre commande shell qui lit son contenu. Dans cette situation, vous n'obtiendrez pas le contenu de la commande shell comme prévu et si vous essayez de déboguer, vous ne pourrez pas trouver le bug facilement. vous pouvez également en savoir plus dans mon blog. http://magnificentzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X