在Python中实现无time.sleep的tail -f

27 投票
10 回答
18383 浏览
提问于 2025-04-15 14:35

我想在Python中模拟“tail -f”这个功能,但我不想在读取循环中使用time.sleep。我想要一种更优雅的方法,比如某种阻塞读取,或者使用select.select加上超时,但Python 2.6的“select”文档明确说:“它不能用于常规文件,以判断文件自上次读取以来是否有增长。”有没有其他的方法呢?

如果几天内没有解决方案,我就打算去看一下tail的C源代码,试着弄明白。我希望他们没有用sleep,嘿嘿。

谢谢。

MarioR

10 个回答

10

在从文件读取数据时,你唯一的选择就是让程序“睡觉”(查看源代码)。如果你是从管道读取数据,那就简单多了,因为读取操作会一直等着,直到有数据可以读取。

之所以这样,是因为操作系统并不支持“等着有人往文件里写数据”这种概念。最近一些文件系统增加了一个可以监听文件变化的接口,但“tail”这个工具太老了,无法使用这个接口,而且这个接口并不是在所有地方都能用。

11

为了减少睡眠问题,我对Tzury Bar Yochay的解决方案进行了修改。现在它会快速检查是否有活动,如果几秒钟内没有活动,它就会每秒检查一次。

import time

def follow(thefile):
    thefile.seek(0,2)      # Go to the end of the file
    sleep = 0.00001
    while True:
        line = thefile.readline()
        if not line:
            time.sleep(sleep)    # Sleep briefly
            if sleep < 1.0:
                sleep += 0.00001
            continue
        sleep = 0.00001
        yield line

logfile = open("/var/log/system.log")
loglines = follow(logfile)
for line in loglines:
    print line,
34

(更新)

你可以使用文件系统监控工具:

或者你也可以使用一个简单的睡眠函数(我觉得这个方法更优雅)。

import time
def follow(thefile):
    thefile.seek(0,2)      # Go to the end of the file
    while True:
         line = thefile.readline()
         if not line:
             time.sleep(0.1)    # Sleep briefly
             continue
         yield line

logfile = open("access-log")
loglines = follow(logfile)
for line in loglines:
    print line

撰写回答