File: tail.py

package info (click to toggle)
python-jtoolkit 0.7.8-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 1,436 kB
  • ctags: 2,536
  • sloc: python: 15,143; makefile: 20
file content (89 lines) | stat: -rw-r--r-- 2,411 bytes parent folder | download | duplicates (2)
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
import os
import sys
import time
from optparse import OptionParser

def tail_lines(fd, linesback = 10, avgcharsperline=75):
    # Contributed to Python Cookbook by Ed Pascoe (2003)
    while 1:
        try:
            fd.seek(-1 * avgcharsperline * linesback, 2)
        except IOError:
            fd.seek(0)

        if fd.tell() == 0:
            atstart = 1
        else:
            atstart = 0

        lines = fd.read().split("\n")
        if (len(lines) > (linesback+1)) or atstart:
            break

        avgcharsperline=avgcharsperline * 1.3

    if len(lines) > linesback:
        start = len(lines) - linesback - 1
    else:
        start = 0

    return lines[start:len(lines)-1]

def reduce_files_to_tail(files, linesback=10, avgcharsperline=75):
    if isinstance(files, str):
        files = [files]
    for fname in files:
        fd = open(fname, 'r')
        lines = tail_lines(fd, linesback, avgcharsperline)
        lines = [line + '\n' for line in lines]
        fd.close()
        print "Writing %d lines to %s" % (linesback, fname)
        fd = open(fname, 'w')
        fd.writelines(lines)
        fd.close()        

def handle_line(line):
    print line,


def do_tail(filename, lines, follow, func = handle_line):
    fd = open(filename, 'r')

    for line in tail_lines(fd, lines):
        func(line + "\n")

    if not follow:
        return

    while 1:
        where = fd.tell()
        line = fd.readline()
        if not line:
            fd_results = os.fstat(fd.fileno())
            try:
                st_results = os.stat(filename)
            except OSError:
                st_results = fd_results

            if st_results[1] == fd_results[1]:
                time.sleep(1)
                fd.seek(where)
            else:
                print "%s changed inode numbers from %d to %d" % (filename, fd_results[1], st_results[1])
                fd = open(filename, 'r')
        else:
            func(line)

def main(argv = sys.argv):
    parser = OptionParser()
    parser.add_option("-n", "--number", action="store", type="int", dest = "number", default=10)
    parser.add_option("-f", "--follow", action="store_true", dest = "follow", default=0)
    (options, args) = parser.parse_args()
    do_tail(args[0], options.number, options.follow, handle_line)

if __name__ == "__main__":
    try:
        main(sys.argv)
    except KeyboardInterrupt:
        pass