Как открыть несколько файлов одновременно в Python? - PullRequest
1 голос
/ 22 мая 2019

У меня есть несколько файлов (число которых априори не определено), которые я хотел бы прочитать одновременно, построчно или фрагментами, выполнить некоторую обработку и перейти ко следующей строке (или фрагменту) во всех файлах.,Я предполагаю, что мои требования более или менее похожи на те, что указаны в в этом вопросе .Тем не менее, в моем случае файлы могут иметь различное количество строк и при попытке реализовать что-то вроде ExitStack заметил, что все файлы будут закрыты, как только один из них будет закрыт (вероятно, это тот, который снаименьшее количество строк), тогда как я хотел бы продолжить обработку других файлов (в конечном итоге назначив пустые строки «строкам» закрытых файлов).Возможно ли это сделать?И как?

#cat f1.txt
RNvn 40
AvOp 13
yEVA 94
oNGn 10
VZQU 88

#cat f2.txt
gSNn 4
zxHP 84
ebRw 70
NaxL 2
lXUb 49
PQzn 79
aIyN 88

#cat f3.txt
XXce 5
RMIq 4
FFEi 47
wuLZ 60

При простой реализации ExitStack результат включает в себя только 4 строки, потому что файл f3.txt имеет всего 4 строки:

flist = ['f1.txt', 'f2.txt', 'f3.txt']
with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in flist]
    for lines in zip(*files):
        print(lines)

# prints
('RNvn 40\n', 'gSNn 4\n', 'XXce 5\n')
('AvOp 13\n', 'zxHP 84\n', 'RMIq 4\n')
('yEVA 94\n', 'ebRw 70\n', 'FFEi 47\n')
('oNGn 10\n', 'NaxL 2\n', 'wuLZ 60\n')

Ответы [ 2 ]

3 голосов
/ 22 мая 2019

Вы можете использовать лучшее из обоих миров.

Код выходит из контекста with ExitStack() as stack:, поскольку zip() исчерпано в самом коротком файле.Это не имеет ничего общего с ExitStack().Использование zip_longest() не исчерпает себя, пока все файлы не будут закончены.Затем ExitStack() закроет файлы.

from contextlib import ExitStack
from itertools import zip_longest

flist = ['f1.txt', 'f2.txt', 'f3.txt']
with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in flist]
    for lines in zip_longest(*files):
        print(lines)
0 голосов
/ 22 мая 2019

Отвечая на мой собственный вопрос, но, пожалуйста, не стесняйтесь добавлять любые заметки / улучшения / альтернативы.

Одним из способов решения этой проблемы является открытие всех файлов без использования оператора with для продолжения чтения до тех пор, пока все файлы не будут прочитаны, и использование zip_longest из itertools для сборавсе линии одновременно.В конце закройте все файлы.Что-то в строках кода ниже должно работать:

from itertools import zip_longest
flist = ['f1.txt', 'f2.txt', 'f3.txt']

files = [open(i, 'rt') for i in flist]
for lines in zip_longest(*files):
    print(lines)

for f in files:
    f.close()

# this prints all lines as expected:
('RNvn 40\n', 'gSNn 4\n', 'XXce 5\n')
('AvOp 13\n', 'zxHP 84\n', 'RMIq 4\n')
('yEVA 94\n', 'ebRw 70\n', 'FFEi 47\n')
('oNGn 10\n', 'NaxL 2\n', 'wuLZ 60\n')
('VZQU 88\n', 'lXUb 49\n', None)
(None, 'PQzn 79\n', None)
(None, 'aIyN 88\n', None)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...