Si vous lisez un fichier entier avec, content = open('Path/to/file', 'r').read()
le descripteur de fichier est-il laissé ouvert jusqu'à la fin du script? Existe-t-il une méthode plus concise pour lire un fichier entier?
Si vous lisez un fichier entier avec, content = open('Path/to/file', 'r').read()
le descripteur de fichier est-il laissé ouvert jusqu'à la fin du script? Existe-t-il une méthode plus concise pour lire un fichier entier?
La réponse à cette question dépend quelque peu de l'implémentation particulière de Python.
Pour comprendre de quoi il s'agit, portez une attention particulière à l' file
objet réel . Dans votre code, cet objet n'est mentionné qu'une seule fois, dans une expression, et devient inaccessible immédiatement après le read()
retour de l' appel.
Cela signifie que l'objet fichier est des ordures. La seule question qui reste est "Quand le garbage collector va-t-il récupérer l'objet fichier?".
dans CPython, qui utilise un compteur de référence, ce type de déchets est immédiatement remarqué et sera donc immédiatement collecté. Ce n'est généralement pas vrai pour les autres implémentations de python.
Une meilleure solution, pour vous assurer que le fichier est fermé, est ce modèle:
with open('Path/to/file', 'r') as content_file:
content = content_file.read()
qui fermera toujours le fichier immédiatement après la fin du bloc; même si une exception se produit.
Edit: Pour mettre un point plus fin dessus:
Autre que file.__exit__()
, qui est appelé "automatiquement" dans un with
paramètre de gestionnaire de contexte, la seule autre manière qui file.close()
est automatiquement appelée (c'est-à-dire autre que de l'appeler explicitement vous-même) est via file.__del__()
. Cela nous amène à la question de savoir quand est __del__()
appelé?
Un programme correctement écrit ne peut pas supposer que les finaliseurs s'exécuteront à un moment quelconque avant la fin du programme.
- https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203
En particulier:
Les objets ne sont jamais explicitement détruits; cependant, lorsqu'ils deviennent inaccessibles, ils peuvent être récupérés. Une implémentation est autorisée à reporter le garbage collection ou à l'omettre complètement - c'est une question de qualité d'implémentation comment le garbage collection est implémenté, tant qu'aucun objet collecté n'est encore accessible.
[...]
CPython utilise actuellement un schéma de comptage de références avec (facultatif) détection retardée des ordures liées cycliquement, qui collecte la plupart des objets dès qu'ils deviennent inaccessibles, mais il n'est pas garanti de collecter les ordures contenant des références circulaires.
- https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types
(Souligner le mien)
mais comme il le suggère, d'autres implémentations peuvent avoir un autre comportement. Par exemple, PyPy a 6 implémentations différentes de la récupération de place !
__exit__()
dans de tels cas ressemble à un défaut de conception.try
/finally
étant délicat et l'utilité très courante des gestionnaires de nettoyage quiwith
résout. La différence entre la «fermeture explicite» et la «gestion avecwith
» est que le gestionnaire de sortie est appelé même si une exception est levée. Vous pouvez mettre leclose()
dans unefinally
clause, mais ce n'est pas très différent de l'utilisation à lawith
place, un peu plus compliqué (3 lignes supplémentaires au lieu de 1), et un peu plus difficile à obtenir juste.with foo() as f: [...]
est fondamentalement la même quef = foo()
,f.__enter__()
[...] etf.__exit__()
avec des exceptions traitées , de sorte que__exit__
toujours appelé. Le dossier est donc toujours fermé.Vous pouvez utiliser pathlib .
Pour Python 3.5 et supérieur:
Pour les anciennes versions de Python, utilisez pathlib2 :
Alors:
Ceci est la
read_text
mise en œuvre réelle :la source
Eh bien, si vous devez lire le fichier ligne par ligne pour travailler avec chaque ligne, vous pouvez utiliser
Ou encore mieux:
la source
Au lieu de récupérer le contenu du fichier sous la forme d'une seule chaîne, il peut être pratique de stocker le contenu sous la forme d'une liste de toutes les lignes du fichier :
Comme on peut le voir, il faut ajouter les méthodes concaténées
.strip().split("\n")
à la réponse principale de ce fil .Ici,
.strip()
supprime simplement les espaces et les caractères de nouvelle ligne à la fin de la chaîne de fichier entière, et.split("\n")
produit la liste réelle en divisant la chaîne de fichier entière à chaque caractère de nouvelle ligne \ n .De plus, de cette façon, tout le contenu du fichier peut être stocké dans une variable, ce qui peut être souhaité dans certains cas, au lieu de parcourir le fichier ligne par ligne comme indiqué dans cette réponse précédente .
la source