Get last n lines of a file, similar to tail

前端 未结 30 2523
挽巷
挽巷 2020-11-22 03:46

I\'m writing a log file viewer for a web application and for that I want to paginate through the lines of the log file. The items in the file are line based with the newest

相关标签:
30条回答
  • 2020-11-22 04:09

    Assumes a unix-like system on Python 2 you can do:

    import os
    def tail(f, n, offset=0):
      stdin,stdout = os.popen2("tail -n "+n+offset+" "+f)
      stdin.close()
      lines = stdout.readlines(); stdout.close()
      return lines[:,-offset]
    

    For python 3 you may do:

    import subprocess
    def tail(f, n, offset=0):
        proc = subprocess.Popen(['tail', '-n', n + offset, f], stdout=subprocess.PIPE)
        lines = proc.stdout.readlines()
        return lines[:, -offset]
    
    0 讨论(0)
  • 2020-11-22 04:09

    you can go to the end of your file with f.seek(0, 2) and then read off lines one by one with the following replacement for readline():

    def readline_backwards(self, f):
        backline = ''
        last = ''
        while not last == '\n':
            backline = last + backline
            if f.tell() <= 0:
                return backline
            f.seek(-1, 1)
            last = f.read(1)
            f.seek(-1, 1)
        backline = last
        last = ''
        while not last == '\n':
            backline = last + backline
            if f.tell() <= 0:
                return backline
            f.seek(-1, 1)
            last = f.read(1)
            f.seek(-1, 1)
        f.seek(1, 1)
        return backline
    
    0 讨论(0)
  • 2020-11-22 04:10

    Simple :

    with open("test.txt") as f:
    data = f.readlines()
    tail = data[-2:]
    print(''.join(tail)
    
    0 讨论(0)
  • 2020-11-22 04:11

    Not the first example using a deque, but a simpler one. This one is general: it works on any iterable object, not just a file.

    #!/usr/bin/env python
    import sys
    import collections
    def tail(iterable, N):
        deq = collections.deque()
        for thing in iterable:
            if len(deq) >= N:
                deq.popleft()
            deq.append(thing)
        for thing in deq:
            yield thing
    if __name__ == '__main__':
        for line in tail(sys.stdin,10):
            sys.stdout.write(line)
    
    0 讨论(0)
  • 2020-11-22 04:12
    import time
    
    attemps = 600
    wait_sec = 5
    fname = "YOUR_PATH"
    
    with open(fname, "r") as f:
        where = f.tell()
        for i in range(attemps):
            line = f.readline()
            if not line:
                time.sleep(wait_sec)
                f.seek(where)
            else:
                print line, # already has newline
    
    0 讨论(0)
  • 2020-11-22 04:12

    Update for answer given by A.Coady

    Works with python 3.

    This uses Exponential Search and will buffer only N lines from back and is very efficient.

    import time
    import os
    import sys
    
    def tail(f, n):
        assert n >= 0
        pos, lines = n+1, []
    
        # set file pointer to end
    
        f.seek(0, os.SEEK_END)
    
        isFileSmall = False
    
        while len(lines) <= n:
            try:
                f.seek(f.tell() - pos, os.SEEK_SET)
            except ValueError as e:
                # lines greater than file seeking size
                # seek to start
                f.seek(0,os.SEEK_SET)
                isFileSmall = True
            except IOError:
                print("Some problem reading/seeking the file")
                sys.exit(-1)
            finally:
                lines = f.readlines()
                if isFileSmall:
                    break
    
            pos *= 2
    
        print(lines)
    
        return lines[-n:]
    
    
    
    
    with open("stream_logs.txt") as f:
        while(True):
            time.sleep(0.5)
            print(tail(f,2))
    
    
    0 讨论(0)
提交回复
热议问题