[Twisted-Python] Where to start: log reader/analysis
Nathaniel Haggard
natester at gmail.com
Mon Aug 13 15:50:04 MDT 2007
Like this?
from twisted.internet import task,reactor,abstract
from twisted.protocols import basic
import os
class FileFollowerTransport(object):
"""Iterate through a file while it is updated.
"""
interval = 1
def __init__(self, filename, interval=None):
self.filename = filename
self.interval = interval or self.interval
self.stat = None
self.offset = 0
self.lines = []
self.lc = task.LoopingCall(self.follow)
#
# File following
def run(self):
self.lc.start(self.interval)
def follow(self):
if self.hasChanged():
data = self.readChange()
if data:
self.protocol.dataReceived(data)
def hasChanged(self):
stat = os.stat(self.filename)
if stat != self.stat:
self.stat = stat
return True
return False
def readChange(self):
file = open(self.filename)
file.seek(self.offset)
data = file.read()
self.offset = file.tell()
file.close()
return data
class stuby(basic.LineReceiver):
def dataReceived(self, data):
print data
if __name__ == '__main__':
l = stuby()
f = FileFollowerTransport('test')
f.protocol = l
f.run()
l.makeConnection(f)
reactor.run()
On 8/6/07, Jean-Paul Calderone <exarkun at divmod.com> wrote:
>
> On Mon, 6 Aug 2007 10:57:19 +0200, Yoann Aubineau <
> yoann.aubineau at wengo.com> wrote:
> >Hi Andrew,
> >
> >I wrote a class that follows a file (eg. log file) and provides an
> iterator
> >to walk through it. Don't know if it may be of any use for you (or
> others).
>
> Hi Yoann, thanks for sharing.
>
> >
> >class FileFollower(object):
> > """Iterate through a file while it is updated.
> >
> > >>> file = FileFollower("/tmp/testfile")
> > >>> file.interval = 5
> > >>> for line in file:
> > ... print line
> > """
> >
> > interval = 1
> >
> > def __init__(self, filename, interval=None):
> > self.filename = filename
> > self.interval = interval or self.interval
> > self.stat = None
> > self.offset = 0
> > self.lines = []
> > self.running = True
> >
> > #
> > # File following
> >
> > def follow(self):
> > while self.running:
> > if self.hasChanged():
> > data = self.readChange()
> > if data:
> > self.dataReceived(data)
> > break
> > time.sleep(self.interval)
> >
> > def hasChanged(self):
> > stat = os.stat(self.filename)
> > if stat != self.stat:
> > self.stat = stat
> > return True
> > return False
> >
> > def readChange(self):
> > file = open(self.filename)
> > file.seek(self.offset)
> > data = file.read()
> > self.offset = file.tell()
> > file.close()
> > return data
> >
> > #
> > # Data buffering
> >
> > def dataReceived(self, data):
> > lines = data.split(os.linesep)
> > lines = lines[:-1]
> > for line in lines:
> > self.lineReceived(line)
> >
> > def lineReceived(self, line):
> > self.lines.append(line)
> >
> > #
> > # Iterator implementation
> >
> > def __iter__(self):
> > return self
> >
> > def next(self):
> > if not self.lines:
> > self.follow()
> > line = self.lines.pop(0)
> > return line
> >
>
> In order to make this class more usable within a Twisted application, I'd
> make a few suggestions:
>
> Separate the transport from the protocol. All of the methods in the area
> commented "file following" are basically transport methods: they know how
> to get the underlying bytes (by polling and eventually reading). The
> protocol implementation is basically the dataReceived and lineReceived
> methods. With separation between the transport and the protocol, you
> don't even need to implement these, since you can just use LineReceiver
> from twisted.protocols.basic.
>
> Do the polling in a cooperative way. Using an infinite for loop and a
> time.sleep call has the consequence of tying up an entire thread. This
> means nothing else can happen unless you run the follow method of this
> class in a new, dedicated thread. If you use the reactor to schedule
> the checks instead, then this can be used alongside other Twisted code
> without having to deal with threading. twisted.internet.task.LoopingCall
> might be of particular interest.
>
> Jean-Paul
>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20070813/6c74965c/attachment.html>
More information about the Twisted-Python
mailing list