Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds a couple of useful options such as adjusting poll time with execute #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 36 additions & 13 deletions tail.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@
import os
import sys
import time
from cStringIO import StringIO

class Tail(object):
''' Represents a tail command. '''
def __init__(self, tailed_file):
def __init__(self, tailed_file, max_line_length=float("inf")):
''' Initiate a Tail instance.
Check for file validity, assigns callback function to standard out.

Expand All @@ -38,25 +39,38 @@ def __init__(self, tailed_file):
self.check_file_validity(tailed_file)
self.tailed_file = tailed_file
self.callback = sys.stdout.write
self.max_line_length=max_line_length

def follow(self, s=1):
def follow(self, s=1, poll_time=.01):
''' Do a tail follow. If a callback function is registered it is called with every new line.
Else printed to standard out.

Arguments:
s - Number of seconds to wait between each iteration; Defaults to 1. '''

with open(self.tailed_file) as file_:
# Go to the end of file
file_.seek(0,2)
readBuffer = StringIO()
with open(self.tailed_file, 'rb') as file_:
file_.seek(0, os.SEEK_END)
while True:
curr_position = file_.tell()
line = file_.readline()
if not line:
file_.seek(curr_position)
else:
readBuffer.write(file_.read())
readBuffer.seek(0)
complete = True
for line in readBuffer:
if not line.endswith(os.linesep):
complete = False
break

self.callback(line)
time.sleep(s)
time.sleep(s)

# Catch the slop if the last line isn't complete
readBuffer.truncate(0)
if not complete:
if len(line) > self.max_line_length:
raise TailError("Line exceeds maximum allowed line length")

readBuffer.write(line)

time.sleep(poll_time)

def register_callback(self, func):
''' Overrides default callback function to provided function. '''
Expand All @@ -71,8 +85,17 @@ def check_file_validity(self, file_):
if os.path.isdir(file_):
raise TailError("File '%s' is a directory" % (file_))

class TailError(Exception):
class TailError(IOError):
def __init__(self, msg):
self.message = msg
def __str__(self):
return self.message

if __name__ == '__main__':
if len(sys.argv) < 2:
print "Usage: python tail.py <filename>"
sys.exit(1)

tail = Tail(sys.argv[1])
tail.follow(0)