1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
"""
logtracker.py
by Jason Conti
February 15, 2010
Tracks a log file for changes.
"""
import os
import os.path
import pyinotify
import time
class LogTracker(pyinotify.ProcessEvent):
"""Tracks a log file for changes."""
def __init__(self, path):
pyinotify.ProcessEvent.__init__(self)
self._path = os.path.abspath(path)
self._offset = self._get_file_length()
self._listeners = set()
def add_listener(self, f):
"""A listener is a function of a single argument, the text appended to
the log when it changed."""
self._listeners.add(f)
def remove_listener(self, f):
"""Removes f from the set of listeners."""
self._listeners.remove(f)
def start(self):
"""Starts watching the file."""
self._wm = pyinotify.WatchManager()
self._wdd = self._wm.add_watch(self._path, pyinotify.IN_MODIFY)
self._notifier = pyinotify.ThreadedNotifier(self._wm, self)
self._notifier.start()
def stop(self):
"""Removes the watch from the tracked file and stops the notifier."""
self._wm.rm_watch(self._wdd.values())
self._notifier.stop()
def _get_file_length(self):
"""Returns the length of the tracked file, returns 0 if there is an error,
assuming that the file may not have been created yet."""
try:
f = open(self._path, "r")
f.seek(0, os.SEEK_END)
size = f.tell()
f.close()
return size
except:
return 0
def _read_appended_text(self):
"""Opens the tracked file, seeks to the last read offset, reads to EOF
and updates the last read offset."""
f = open(self._path, "r")
f.seek(self._offset, os.SEEK_SET)
text = f.read()
self._offset = f.tell()
f.close()
return text
def process_IN_MODIFY(self, event):
"""Reads the appended text in the tracked file and sends it to the listeners."""
text = self._read_appended_text()
for f in self._listeners:
f(text)
def test1(text):
print "test1:"
print text
def test2(text):
print "test2:"
print text
def main():
track = LogTracker("test.log")
track.add_listener(test1)
track.add_listener(test2)
while True:
try:
time.sleep(10000)
except:
track.stop()
break
if __name__ == '__main__':
main()
|