【问题标题】:Re-reading file when cycling over a file object in Python在Python中循环文件对象时重新读取文件
【发布时间】:2012-07-04 15:46:25
【问题描述】:

从这个上下文:

import itertools
lines = itertools.cycle(open('filename'))

我想知道如何实现相同的“功能”,但在文件到达末尾时重新读取文件,因此如果文件在第一次迭代后发生更改,它会在开始另一个循环之前重新加载。 (希望我已经解释清楚了)

提前感谢您! :)

【问题讨论】:

    标签: python


    【解决方案1】:

    我会使用:

    itertools.chain.from_iterable(itertools.starmap(open, itertools.repeat(("filename",))))
    

    或:

    itertools.chain.from_iterable(itertools.starmap(lambda: open("filename"), itertools.repeat(())))
    

    你也可以写一个生成器理解(我想我最喜欢这个!):

    (line for _ in itertools.repeat(()) for line in open("filename"))
    

    这是命令式(基于语句的)等价物:

    def cycle_file(filename):
        while True:
            for line in open(filename):
                yield line
    

    或者,使用 Python 3.3(使用 PEP 380 子生成器委托):

    def cycle_file(filename):
        while True:
            yield from open(filename)
    

    所有这些的一个问题是(在 GC 平台上,例如 Jython)在文件对象被 GC 之前不会关闭文件,这可能会在稍后发生。为防止打开的文件泄漏,您必须在其上调用close 或使用上下文管理器(with 语句)。这很自然地以命令式形式出现:

    def cycle_file(filename):
        while True:
            with open(filename) as f:
                for line in f:
                    yield line
    

    或

    def cycle_file(filename):
        while True:
            with open(filename) as f:
                yield from f
    

    试图用生成器理解关闭文件变得非常做作:

    (line for f in (itertools.chain(f, (f for f in (f,) if f.close() and False))
                    for f in (open("filename") for _ in itertools.repeat(())))
     for line in f)
    

    如果 Python 能够指定 opened 文件在到达文件末尾时自行关闭,或者告诉上下文管理器迭代器在 StopIteration 上自行关闭,那就太好了。

    【讨论】:

    • 是的,我也更喜欢最后一种方式,似乎更容易理解! :) 也很喜欢 Python 3.3 版本的代码,很好的提醒我需要更新自己!谢谢!! :)
    • while True 似乎是最易读的。您可以将其改编为 Python for line in open(filename)): yield line
    • 为了避免fd泄漏with语句可以使用
    • 好的,完成 - 我认为命令式版本开始出现在首位
    • 是的,现在我可以选择经过调整的命令式版本(确实是最易读的版本!),再次感谢所有支持! :)
    【解决方案2】:

    类似

    def cycle_file(f):
        while True:
            ln = f.readline()
            if ln == "":
                f.seek(0)
                continue
            yield ln
    

    除了检查空文件可能会很好,我会留给你。

    【讨论】:

    • 这会在最后产生空字符串,对吧?可能是错误或功能。
    • @DSM:我忘记了continue 声明。谢谢。
    • 如果文件被替换,这可能会丢失更改(tail -f 与 tail -F)
    • 虽然我选择了@ecatmur 的生成器理解方式,但我喜欢你的代码直观性!感谢您提供空文件提示,如果您没有建议我可能会忘记它! :)
    猜你喜欢
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    相关资源
    最近更新 更多