0
votes

Lire des fichiers dans une seule expression, les fermez correctement

Je veux lire le contenu d'une liste de fichiers à Python. Ma première idée a été

contenu = [Ouvrir (F) .Read () pour F dans les fichiers]

mais qui laisse les fichiers ouverts jusqu'à ce que les objets soient recueillis, et montre ressourcewarning .

fermeture des fichiers nécessite plusieurs compréhensions: xxx

... ce qui est non naturel.

ou une boucle: xxx

... qui est assez verbeux et longue à lire.

y a-t-il une autre alternative? < / p>


5 commentaires

Mais cela laisse les fichiers ouverts jusqu'à ce que les objets soient des ordures recueillies - pas vrai (principalement). Dans CPPHON, chaque fichier est fermé car son compte REF passe à 0 à l'intérieur du générateur. Le collecteur des ordures n'est pas impliqué dans la suppression de la plupart des objets - il n'entre en jeu que lorsque des références ambiguës empêchent le décréfre ordinaire de la réalisation de l'objet est " Del " - capable. Certains Pythons alternatifs ne sont pas de même, mais pour CPPHON, je serais personnellement à l'aise avec votre doublure d'origine.


@TDelaney merci pour le contexte! Par "déchets collectés" ici, je voulais dire la collecte des ordures générales, y compris le comptage de référence, pas seulement gc . Certes, le terme «collection à la poubelle» est ambigu lorsque nous parlons de CPPHON, et je conviens que les exemples fonctionnent parfaitement bien. Dans mon cas particulier, je sais avec certitude que je dois prendre en charge des implémentations non-CPPHON. Et en général, je pense qu'il est raisonnable d'écrire Python comme spécifié par la langue, par opposition à la mise en œuvre de la référence.


Oui, je peux faire un accord à contrecœur. Je suis toujours têtu de ma conviction que Ref Comptage devrait être canonique. Ce n'était pas jusqu'à ce que les implémentations secondaires (et non-conformes à l'IMHO) telles que Jython se produisent que c'était un problème. Votre exemple est la raison exacte pour laquelle les comptes REF sont bons. La gestion des ressources est le problème numéro un avec une langue telle que C et Python est censé résoudre celui-là.


@TDelaney quand vous dites "non-conformité", voulez-vous dire que la spécification de la langue a été modifiée lorsque Jython est arrivé? Je suis d'accord, il serait certainement agréable d'avoir l'exemple initial "juste du travail", mais la réponse de Kichik est encore plus explicite, à mon avis. J'ai trouvé le PYPY Page Distance des différences de collecte des ordures très intéressantes


@goncaloop - Je ne suis pas sûr de la manière dont la spécification était formelle à l'époque - CPPHON est la mise en œuvre de référence, donc dans un sens quelconque il se passe à faire est la spécification. La compilation Jython à Java Bytecode a un modèle de gestion de ressources différent (d'autres implémentations de Python également) mais c'est un peu de la queue remuant le chien à obstruer les fonctionnalités utiles à cause d'eux, IMHO. Python a introduit la collecte des ordures cycliques pour traiter les problèmes de compte de référence, mais j'aime certainement la fonctionnalité quel que soit le risque.


3 Réponses :


0
votes

Vous pouvez utiliser une fonction:

def read_contents(filename):
    with open(filename) as file:
        return file.read()

contents = [read_contents(f) for f in files]


0 commentaires

2
votes

Vous pouvez utiliser pathlib pour cela.

class Path:

    # ....

    def read_bytes(self):
        """
        Open the file in bytes mode, read it, and close the file.
        """
        with self.open(mode='rb') as f:
            return f.read()

    def read_text(self, encoding=None, errors=None):
        """
        Open the file in text mode, read it, and close the file.
        """
        with self.open(mode='r', encoding=encoding, errors=errors) as f:
            return f.read()


1 commentaires

pathlib devient rapidement l'un de mes modules préférés. Merci!



1
votes

Vous pouvez utiliser le CODE> EXITSTACK CODE> Contexte Manager. Votre cas d'utilisation est une légère variation de l'exemple indiqué dans la documentation.

from contextlib import ExitStack

with ExitStack() as es:
    contents = [es.enter_context(open(f)).read() for f in files]


0 commentaires