我将解决两个问题:
- 如何
tail
在文件上实现,
- 以及如何使用该
pyinotify
模块。
文件尾
在您的代码中,您需要:
- 尝试阅读尽可能多的完整行,使用
read
or readlines
,
- 将文件倒回到最后一个不完整行的开头,直到您可以使用
seek
.
例如,这转化为:
f = open(PATH)
for line in f.readlines():
print line[:-1]
while True:
time.sleep(5)
try:
line_start = f.tell()
new_lines = f.read()
last_n = new_lines.rfind('\n')
if last_n >= 0:
# We got at least one full line
line_start += last_n + 1
print new_lines[:last_n]
else:
# No complete line yet
print 'no line'
f.seek(line_start)
except KeyboardInterrupt:
notifier.stop()
break
您可以在此处找到更多示例,尽管有些示例并未解决文件中不以换行符结尾的添加内容:
还有一些替代方法如何在 Python 中跟踪日志文件?
Pyinotify 循环
您还应该pyinotify
按照文档中的说明将代码移动到 的事件处理程序中。
check_events
如果有要处理的事件则返回True
,但它实际上并不处理事件,因此它本身将始终返回True
,直到处理完事件。
另外,尽量避免while
/sleep
循环。Inotify 添加了在收到事件后立即处理事件的能力,而不会影响资源。A while
/sleep
循环将不那么被动。
以下是 .上的简短教程中的两种第一种方法pyinotify
。
1.无休止的监控
如果您没有其他事件循环,这是首选方法,因为它将是最具反应性的:
PATH = os.path.join(os.path.expanduser('~/'), 'experiments', 'testfile')
class EventHandler(pyinotify.ProcessEvent):
def __init__(self, *args, **kwargs):
super(EventHandler, self).__init__(*args, **kwargs)
self.file = open(PATH)
self.position = 0
self.print_lines()
def process_IN_MODIFY(self, event):
print 'event received'
self.print_lines()
def print_lines(self):
new_lines = self.file.read()
last_n = new_lines.rfind('\n')
if last_n >= 0:
self.position += last_n + 1
print new_lines[:last_n]
else:
print 'no line'
self.file.seek(self.position)
wm = pyinotify.WatchManager()
handler = EventHandler()
notifier = pyinotify.Notifier(wm, handler)
wm.add_watch(PATH, pyinotify.IN_MODIFY, rec=True)
notifier.loop()
2. 定期监测
如果您已经有一个处理循环,那么只需process_events
定期调用即可。该类与方法 1 中的EventHandler
类相同,但现在notifier.loop()
我们不是调用,而是向通知程序添加一个小超时,并实现我们自己的事件循环。
...
wm = pyinotify.WatchManager()
handler = EventHandler()
notifier = pyinotify.Notifier(wm, handler, timeout=10)
wm.add_watch(PATH, pyinotify.IN_MODIFY, rec=True)
while True:
# Do something unrelated to pyinotify
time.sleep(5)
notifier.process_events()
#loop in case more events appear while we are processing
while notifier.check_events():
notifier.read_events()
notifier.process_events()