从频繁更新的文件中读取
我现在在Linux系统上用Python写一个程序。这个程序的目标是读取一个日志文件,并在找到特定字符串时执行一个bash命令。这个日志文件是由另一个程序不断写入的。
我的问题:如果我用open()
方法打开这个文件,我的Python文件对象会随着实际文件的更新而自动更新吗?还是说我需要定时重新打开这个文件?
更新:感谢大家的回答。我可能应该提到,这个文件是由一个Java EE应用程序写入的,所以我无法控制数据何时被写入。目前我有一个程序每10秒重新打开文件,并尝试从上次读取到的字节位置继续读取。现在它只是打印出返回的字符串。我希望这个文件不需要重新打开,而是读取命令能够直接访问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)
谢谢你们关于pyinotify和生成器的建议。我会看看这些,寻找更好的解决方案。
9 个回答
14
这是对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)
27
“一次互动的交流胜过千言万语。”
>>> 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'
换句话说 - 是的,打开一次就够了。
127
我建议你看看David Beazley的Python中的生成器技巧,特别是第5部分:处理无限数据。这部分会教你如何在实时处理中实现类似于tail -f logfile
命令的功能。
# 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,