web-dev-qa-db-fra.com

La fermeture explicite de fichiers est-elle importante?

En Python, si vous ouvrez un fichier sans appeler close() ou fermez le fichier sans utiliser try-finally ou l'instruction "with" , est-ce un problème? Ou suffit-il comme pratique de codage de s’appuyer sur le Python garbage-collection pour fermer tous les fichiers? Par exemple, si l’on fait ceci:

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

... s'agit-il d'un problème, car le fichier ne peut jamais être fermé et une exception pourrait l'empêcher d'être fermé? Ou sera-t-il définitivement fermé à la fin de l'instruction for parce que le fichier est hors de portée?

136
user553702

Dans votre exemple, la fermeture du fichier n’est pas garantie avant la sortie de l’interprète. Dans les versions actuelles de CPython, le fichier sera fermé à la fin de la boucle for, car CPython utilise le décompte de références comme mécanisme principal de récupération de place, mais il s'agit d'un détail de l'implémentation et non d'une fonctionnalité du langage. Les autres implémentations de Python ne fonctionnent pas de cette façon. Par exemple, IronPython, PyPy et Jython n'utilisent pas le comptage de références et ne ferment donc pas le fichier à la fin de la boucle. .

Il est déconseillé de s'appuyer sur l'implémentation de la récupération de place de CPython, car elle 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 jamais à une implémentation Python qui n’utilise pas le comptage de références, vous devrez passer en revue tout votre code et vous assurer que vos fichiers sont bien fermés.

Pour votre exemple, utilisez:

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

Certains Pythons fermeront automatiquement les fichiers quand ils ne seront plus référencés, d'autres non et il appartiendra au système d'exploitation de fermer les fichiers lorsque l'interprète Python sera fermé.).

Même pour les Pythons qui vont fermer les fichiers pour vous, le timing n'est pas garanti: cela peut être immédiat, ou il peut être quelques secondes/minutes/heures/jours plus tard.

Par conséquent, même si vous ne rencontrez peut-être pas de problèmes avec le Python que vous utilisez, il n’est certainement pas recommandé de laisser vos fichiers ouverts. En fait, dans cpython 3, vous recevrez maintenant un avertissement indiquant que le système dû fermer des dossiers pour vous si vous ne le faisiez pas.

Morale: Nettoyez-vous après vous-même. :)

22
Ethan Furman

Bien qu'il soit tout à fait sûr d'utiliser une telle construction dans ce cas particulier, il convient de généraliser cette pratique:

  • run peut potentiellement manquer de descripteurs de fichiers, bien que cela soit peu probable, imaginez que vous recherchiez un bogue comme celui-ci.
  • vous ne pourrez peut-être pas supprimer ce 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 vidées
9
Dima Tisnek

Bonjour, Il est très important de fermer votre descripteur de fichier au cas où vous utiliseriez son contenu dans le même script python. Je me rends aujourd'hui compte après un débogage aussi long. Le motif en est le contenu être édité/supprimé/enregistré uniquement après la fermeture du descripteur de fichier et que les modifications sont affectées au fichier!

Supposons donc que vous écrivez du contenu dans un nouveau fichier et que, sans fermer fd, vous utilisez ce fichier (pas 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 trouverez pas facilement le bogue. vous pouvez également lire plus dans mon entrée de blog http://magnificentzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html

3
Zeel Shah

Le fichier est effectivement récupéré et donc fermé. Le GC détermine quand il se ferme, pas vous. De toute évidence, ce n'est pas une pratique recommandée car vous pourriez atteindre le nombre maximal de descripteurs de fichiers si vous ne fermez pas les fichiers dès que vous avez fini de les utiliser. Et si dans votre for boucle, vous ouvriez plus de fichiers et les laissiez en attente?

3
Nam Nguyen

Au cours du processus d'E/S, les données sont mises en mémoire tampon: cela signifie qu'elles sont conservées dans un emplacement temporaire avant d'être écrites dans le fichier.

Python ne vide pas le tampon, c’est-à-dire n’écrit des données dans le fichier, que s’il est certain que l’écriture est terminée. Une façon de faire est de fermer le fichier.

Si vous écrivez dans un fichier sans fermer, les données ne parviendront pas dans le fichier cible.

1
Sanket Nagrale