【问题标题】:How to open multiple files simultaneously in Python?如何在 Python 中同时打开多个文件?
【发布时间】:2019-05-21 22:51:41
【问题描述】:

我有一些文件(其数量未预先确定),我想逐行或分块同时读取,进行一些处理并移至所有文件中的下一行(或块) .我想我的要求或多或少类似于this question 中的要求。但是,在我的情况下,文件可以有不同的行数,并且在尝试实现类似 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')

【问题讨论】:

    标签: python-3.x file


    【解决方案1】:

    您可以两全其美。

    代码将离开上下文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)
    

    【讨论】:

    • 哦,诀窍实际上在于使用zip_longest,而与ExitStack 无关。也会更新我的答案。
    【解决方案2】:

    回答我自己的问题,但请随时添加任何注释/改进/替代方案。

    解决此问题的一种方法是打开所有文件,而不使用with 语句继续读取直到读取所有文件,并使用itertools 中的zip_longest 同时收集所有行。最后关闭所有文件。以下代码行中的某些内容应该可以工作:

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-09
      • 2020-01-26
      • 1970-01-01
      • 1970-01-01
      • 2017-06-10
      • 2011-06-04
      相关资源
      最近更新 更多