Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

tail -f with python

2 views
Skip to first unread message

Roy Marteen

unread,
Aug 3, 2002, 2:41:26 PM8/3/02
to
Hi,

How can I write in Python something like 'tail -f filename'? I mean, when
there is an append to the file, it will be displayed real time.

I tried this:

while 1:
line = open('test', 'r').readline()
print line

But it keeps looping, eventhough there is no change (append) in file
'test'. Please help, and thanks very much.

Erik Max Francis

unread,
Aug 3, 2002, 3:16:27 PM8/3/02
to
Roy Marteen wrote:

You probably want to emulate the behavior of tail -f itself.
Disregarding the initial display of the last few lines of the file, seek
to the end of the file (you may have to open the file in binary format
for this), get the current file pointer position, try to read lines. If
you get end of file errors, wait a little bit, seek back to that current
file pointer position, and try to read again.

Try something like this (note this will cat the whole file to start
with):

while 1:
where = file.tell()
line = file.readline()
if not line: # EOF reached
time.sleep(1) # or however long
file.seek(where) # defaults to absolute positioning
else:
print line, # already has newline

Obviously this must work on a file object which supports .seek and .tell
methods.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/ \ See the son in your bad day / Smell the flowers in the valley
\__/ Chante Moore
Bosskey.net: Aliens vs. Predator 2 / http://www.bosskey.net/avp2/
A personal guide to Aliens vs. Predator 2.

holger krekel

unread,
Aug 3, 2002, 2:57:29 PM8/3/02
to
Roy Marteen wrote:
> How can I write in Python something like 'tail -f filename'? I mean, when
> there is an append to the file, it will be displayed real time.
>
> I tried this:
>
> while 1:
> line = open('test', 'r').readline()
> print line
>
> But it keeps looping, ...

as it should. it reads the first line of 'test' and prints it,
virtually forever.

There are two possibilities. First is simply invoking 'tail -f'
in the background, basically:

import os
tailoutputfile = os.popen('tail -f syslog')
while 1:
line = tailoutputfile.readline()
if len(line)==0: # change the termination condition
break
process_line(line)


second is doing what 'tail -f' does itself. Basically:

lastsize=os.path.getsize('filename')
while 1:
size=os.path.getsize('filename')
if size>lastsize:
f=open('filename')
f.seek(lastsize)
part = f.read(size-lastsize) # reads chunks, not lines!
f.close()
process_next_part(part)
elif size==lastsize:
time.sleep(0.2) # seconds to wait
elif size<lastsize:
print >>sys.stderr, "file filename got truncated"
lastsize=size


The code is hopefully self-explaining enough.
If not, feel free to ask.

regards,

holger

Skip Montanaro

unread,
Aug 3, 2002, 3:01:47 PM8/3/02
to
Roy> How can I write in Python something like 'tail -f filename'? I
Roy> mean, when there is an append to the file, it will be displayed
Roy> real time.

Try something like this (only very lightly tested):

#!/usr/bin/env python

import os
import sys
import time

offset = 0
fname = sys.argv[1]
try:
while 1:
size = os.path.getsize(fname)
if size > offset:
f = open(fname, 'r')
f.seek(offset)
sys.stdout.write(f.read())
f.close()
offset = size
time.sleep(0.1)
except KeyboardInterrupt:
pass

--
Skip Montanaro
sk...@pobox.com
consulting: http://manatee.mojam.com/~skip/resume.html

holger krekel

unread,
Aug 3, 2002, 3:08:18 PM8/3/02
to
Skip Montanaro wrote:
> Roy> How can I write in Python something like 'tail -f filename'? I
> Roy> mean, when there is an append to the file, it will be displayed
> Roy> real time.
>
> Try something like this (only very lightly tested):
>
> #!/usr/bin/env python
>
> import os
> import sys
> import time
>
> offset = 0
> fname = sys.argv[1]
> try:
> while 1:
> size = os.path.getsize(fname)
> if size > offset:
> f = open(fname, 'r')
> f.seek(offset)
> sys.stdout.write(f.read())
> f.close()
> offset = size
> time.sleep(0.1)

typo alarm!

you probably want time.sleep(0.1) to be indented here:

time.sleep(0.1)

otherwise you consume 100% CPU-time if the file doesn't
change.

> except KeyboardInterrupt:
> pass

that's for additional educational purposes, right?

regards,

holger

Skip Montanaro

unread,
Aug 3, 2002, 11:18:14 PM8/3/02
to
holger> typo alarm!

holger> you probably want time.sleep(0.1) to be indented here:

holger> time.sleep(0.1)

Like I said:

>> Try something like this (only very lightly tested):

S

0 new messages