【问题标题】:Reading infinite stream - tail读取无限流 - 尾
【发布时间】:2017-12-07 07:26:36
【问题描述】:

问题:

程序从文件末尾开始从无限流中读取行。

#解决方案:

import time
def tail(theFile):
    theFile.seek(0,2)   # Go to the end of the file
    while True:
        line = theFile.readline()
        if not line:
            time.sleep(10)    # Sleep briefly for 10sec
            continue
        yield line

if __name__ == '__main__':
    fd = open('./file', 'r+')
    for line in tail(fd):
        print(line)

readline() 是非阻塞读取,每行都进行 if 检查。

问题:

在写入文件的进程有close()之后,我的程序运行无限等待是没有意义的

1) 该代码的 EAFP 方法是什么,以避免if

2) 生成器函数可以在file 关闭时返回吗?

【问题讨论】:

  • “如果不检查,该代码的 EAFP 方法是什么?” - 真的没什么。您使用 if 语句的原因不是为了防止 Python 引发错误,而是为了验证 line 实际上有有用的内容要返回。 Python 不在乎这是否属实。无论如何,它都会产生line 而不会引发错误。
  • @ChristianDean EAFP 不鼓励在引用 (yield line) 名称之前对名称进行条件检查。
  • 我明白这一点。但是没有什么可以请求宽恕的。从 Python 的角度来看,您没有做错任何事情。同样,Python 不关心 line 是否为空。不管怎样,它都会执行yield line。在这里使用try/except 块实际上是没有用的。坚持使用if
  • @ChristianDean 可以在循环中向continue 表示宽恕。宽恕部分不需要引发异常。我不应该在except 块中写continue 吗?
  • 好的。但这仍然不能解决问题。 请求宽恕也不例外。因为line 是空的,所以不会在您的函数中引发错误。因此,请求原谅是没有意义的。

标签: python python-3.x stream generator pipeline


【解决方案1】:

@ChristianDean 在他的comment 中很好地回答了您的第一个问题,所以我将回答您的第二个问题。

我相信这是可能的 - 如果文件已关闭,您可以使用 theFileclosed 属性并引发 StopIteration 异常。像这样:

def tail(theFile):
    theFile.seek(0, 2) 
    while True:
        if theFile.closed:
            raise StopIteration

        line = theFile.readline()
        ...
        yield line

当文件关闭并引发异常时,您的循环将停止。


不涉及显式异常的更简洁的方法(感谢 Christian Dean)是测试循环头中的文件指针。

def tail(theFile):
    theFile.seek(0, 2) 
    while not theFile.closed:
        line = theFile.readline()
        ...
        yield line

【讨论】:

  • 你说得对,他可以这样实现生成器。但是,StopIteration 真的只是多余的。他所要做的就是在文件关闭时打破他的while循环(while not theFile.closed),仅此而已。 Python 将自动处理生成器的StopIteration。除非您创建自定义生成器对象,否则您不必提高 StopIteration
  • @ChristianDean 完全有道理!非常感谢。
  • @ChristianDean theFile.closed?这行得通吗?我的程序已打开file 供阅读(通过fd),theFile.closed 怎么可能是True?这不起作用
  • @overexchange 如果您希望看到coldspeed 的代码确实有效,我创建了一个小的repl.it 会话here。如您所知,当我们在 for 循环内调用 fd.close() 时,生成器会在下一次调用时结束,并在读取 file.txt 中的所有数据之前停止。这表明它确实响应了从函数外部关闭的fd。唯一需要注意的是我删除了theFile.seek(0, 2),因为这会产生任何视觉输出,我认为这对于证明这一点很重要。
  • @cᴏʟᴅsᴘᴇᴇᴅ 谢谢。时间够长了! :-) Now to see what new privileges 我有 ;-)
猜你喜欢
  • 2016-05-31
  • 2019-11-25
  • 2012-03-12
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 2013-06-05
  • 1970-01-01
  • 2016-07-13
相关资源
最近更新 更多