从经常更新的文件中读取

Jim*_*imS 49 python file-io fopen

我目前正在Linux系统上用python编写程序.目标是在找到特定字符串时读取日志文件并执行bash命令.日志文件由另一个程序不断写入.我的问题是:

如果我使用open()方法打开文件,我的Python文件对象会在实际文件被其他程序写入时更新,还是我必须按时间间隔重新打开文件?

谢谢

吉姆

更新:到目前为止,感谢您的答案.我或许应该提到该文件是由Java EE应用程序编写的,因此我无法控制何时将数据写入其中.我目前有一个程序每隔10秒重新打开一次该文件,并尝试从它上次读取的文件中的字节位置读取.目前它只打印出返回的字符串.我希望文件不需要重新打开,但是read命令可以以某种方式访问​​Java应用程序写入文件的数据.

#!/usr/bin/python
import time

fileBytePos = 0
while True:
    inFile = open('./server.log','r')
    inFile.seek(fileBytePos)
    data = inFile.read()
    print data
    fileBytePos = inFile.tell()
    print fileBytePos
    inFile.close()
    time.sleep(10)
Run Code Online (Sandbox Code Playgroud)

感谢pyinotify和发电机的提示.我打算看看这些更好的解决方案.

Jef*_*uer 87

我建议看一下David Beazley的Python Generator技巧,特别是第5部分:处理无限数据.它将tail -f logfile实时处理Python等效的命令.

# follow.py
#
# Follow a file like tail -f.

import time
def follow(thefile):
    thefile.seek(0,2)
    while True:
        line = thefile.readline()
        if not line:
            time.sleep(0.1)
            continue
        yield line

if __name__ == '__main__':
    logfile = open("run/foo/access-log","r")
    loglines = follow(logfile)
    for line in loglines:
        print line,
Run Code Online (Sandbox Code Playgroud)

  • 如果答案包含 OP 代码方面的代码示例,我会赞成。 (2认同)
  • 这个答案恕我直言是错误的,如果作者在两个单独的块中写一行,则 readline 将返回两次。但你真的只想返回一行。 (2认同)

jsb*_*eno 17

"互动环节值1000字"

>>> f1 = open("bla.txt", "wt")
>>> f2 = open("bla.txt", "rt")
>>> f1.write("bleh")
>>> f2.read()
''
>>> f1.flush()
>>> f2.read()
'bleh'
>>> f1.write("blargh")
>>> f1.flush()
>>> f2.read()
'blargh'
Run Code Online (Sandbox Code Playgroud)

换句话说 - 是的,单一的"开放"就行了.


And*_*nko 5

这是Jeff Bauer答案的略微修改版本,可抵抗文件截断。如果文件正在由处理非常有用logrotate

import os
import time

def follow(name):
    current = open(name, "r")
    curino = os.fstat(current.fileno()).st_ino
    while True:
        while True:
            line = current.readline()
            if not line:
                break
            yield line

        try:
            if os.stat(name).st_ino != curino:
                new = open(name, "r")
                current.close()
                current = new
                curino = os.fstat(current.fileno()).st_ino
                continue
        except IOError:
            pass
        time.sleep(1)


if __name__ == '__main__':
    fname = "test.log"
    for l in follow(fname):
        print "LINE: {}".format(l)
Run Code Online (Sandbox Code Playgroud)

  • 害怕看到`while True:while True:` (3认同)