Читайте файлы в одном выражении, правильно закрывая их - PullRequest
0 голосов
/ 29 февраля 2020

Я хочу прочитать содержимое списка файлов в python. Моя первая идея была

contents = [open(f).read() for f in files]

Но это оставляет файлы открытыми до тех пор, пока объекты не будут собраны мусором, и показывает ResourceWarning.

Закрытие файлов требует нескольких пониманий :

fds = [open(f) for f in files]
contents = [fd.read() for fd in fds]
[fd.close() for fd in fds]

... что неестественно.

или al oop:

contents = []
for f in files:
    with open(f) as fd:
        contents.append(f.read())

... что довольно многословно и долго читать .

Есть ли другая альтернатива?

Ответы [ 3 ]

2 голосов
/ 29 февраля 2020

Для этого вы можете использовать pathlib .

from pathlib import Path
contents_text = [Path(f).read_text() for f in files]
contents_bytes = [Path(f).read_bytes() for f in files]

Внутри это просто:

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 голос
/ 29 февраля 2020

Вы можете использовать менеджер контекста ExitStack. Ваш вариант использования незначительно отличается от примера, приведенного в документации.

from contextlib import ExitStack

with ExitStack() as es:
    contents = [es.enter_context(open(f)).read() for f in files]
0 голосов
/ 29 февраля 2020

Вы можете использовать функцию:

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

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