您将需要使用“状态机”。这只是一种奇特的说法,你想跟踪你在文件中的位置,所以你把seek() 到那个位置,read() 到文件末尾,每次你读取并推进当前位置遇到换行符。
你可以使用这样的东西,也可以像迭代器一样使用:
import time
class LogFollower:
def __init__(self, fp):
self.position = 0
self.fp = fp
def seek(self):
self.fp.seek(self.position)
def has(self):
self.seek()
return '\n' in self.fp.read()
def __iter__(self):
while self.has():
self.seek()
line = self.fp.read().split('\n')[0]
yield line
# advance position - this is the 'state machine' part!
self.position += len(line) + 1
follow = LogFollower(open("my_file.txt"))
# assume the file already has 2 lines
for line in follow:
print(line)
#>foo
#>bar
time.sleep(5)
# now suppose a line 'baz' is added to the bottom
# somewhere during those 10 secs, then you decide
# to iterate again.
for line in follow:
print(line)
#>baz
您还可以通过再次迭代来不断检查它是否有新行,如上面的假设示例所示,当附加 baz 时。
请注意,这样一来,每一行都必须以换行符结束 (\n)。这让事情变得更简单,我想这可能就是为什么它是通常的约定。
这个例子比像this one 这样的简单的readline 循环更实际一些。我认为这种方式需要更多的行数。但是,我认为出于说明目的,它更清洁;我想它在用简单的面向对象编程解释任务的基础方面做得很好。
附:我打电话给seek 的次数可能比我真正需要的要多。例如,在__next__ 中每次运行for 循环之后,我可以不在has() 函数中调用它。不过,为了说明清楚起见,我决定保持这种方式。 :)
附言我知道这并不是真正的状态机。我的意思是非常广泛的。实际的有限状态机是一个完全不同的概念。所有这一切都是在每次遇到新行时增加一个计数器。我希望这不会太误导,而且我试图表达的实际观点仍然很清楚——保持跟踪。