Получить последние n строк файла с Python, похожего на tail - PullRequest
167 голосов
/ 26 сентября 2008

Я пишу средство просмотра файла журнала для веб-приложения, и для этого я хочу разбить на страницы строки файла журнала. Элементы в файле являются строками, основанными на самом новом элементе внизу.

Так что мне нужен метод tail(), который может читать n строки снизу и поддерживает смещение. То, что я придумал, выглядит так:

def tail(f, n, offset=0):
    """Reads a n lines from f with an offset of offset lines."""
    avg_line_length = 74
    to_read = n + offset
    while 1:
        try:
            f.seek(-(avg_line_length * to_read), 2)
        except IOError:
            # woops.  apparently file is smaller than what we want
            # to step back, go to the beginning instead
            f.seek(0)
        pos = f.tell()
        lines = f.read().splitlines()
        if len(lines) >= to_read or pos == 0:
            return lines[-to_read:offset and -offset or None]
        avg_line_length *= 1.3

Это разумный подход? Каков рекомендуемый способ подгонки файлов журнала со смещением?

Ответы [ 30 ]

0 голосов
/ 12 мая 2013

Мне пришлось прочитать определенное значение из последней строки файла и наткнуться на этот поток. Вместо того, чтобы заново изобретать колесо в Python, я получил крошечный скрипт оболочки, / USR / местные / бен / get_last_netp:

#! /bin/bash
tail -n1 /home/leif/projects/transfer/export.log | awk {'print $14'}

А в программе Python:

from subprocess import check_output

last_netp = int(check_output("/usr/local/bin/get_last_netp"))
0 голосов
/ 18 июня 2018

Я нашел, вероятно, самый простой способ найти первые или последние N строк файла

Последние N строк файла (например, N = 10)

file=open("xyz.txt",'r")
liner=file.readlines()
for ran in range((len(liner)-N),len(liner)):
    print liner[ran]

Первые N строк файла (например, N = 10)

file=open("xyz.txt",'r")
liner=file.readlines()
for ran in range(0,N+1):
    print liner[ran]
0 голосов
/ 20 июня 2018

это так просто:

def tail(fname,nl):
with open(fname) as f:
    data=f.readlines() #readlines return a list
    print(''.join(data[-nl:]))
0 голосов
/ 04 марта 2018
import itertools
fname = 'log.txt'
offset = 5
n = 10
with open(fname) as f:
    n_last_lines = list(reversed([x for x in itertools.islice(f, None)][-(offset+1):-(offset+n+1):-1]))
0 голосов
/ 17 июня 2018
abc = "2018-06-16 04:45:18.68"
filename = "abc.txt"
with open(filename) as myFile:
    for num, line in enumerate(myFile, 1):
        if abc in line:
            lastline = num
print "last occurance of work at file is in "+str(lastline) 
0 голосов
/ 26 сентября 2008

Если подумать, это, вероятно, так же быстро, как и здесь.

def tail( f, window=20 ):
    lines= ['']*window
    count= 0
    for l in f:
        lines[count%window]= l
        count += 1
    print lines[count%window:], lines[:count%window]

Это намного проще. И это, кажется, рвется в хорошем темпе.

0 голосов
/ 12 мая 2013

Не первый пример использования deque, но более простой. Это общее правило: оно работает с любым повторяемым объектом, а не только с файлом.

#!/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 голосов
/ 25 апреля 2014
This is my version of tailf

import sys, time, os

filename = 'path to file'

try:
    with open(filename) as f:
        size = os.path.getsize(filename)
        if size < 1024:
            s = size
        else:
            s = 999
        f.seek(-s, 2)
        l = f.read()
        print l
        while True:
            line = f.readline()
            if not line:
                time.sleep(1)
                continue
            print line
except IOError:
    pass
0 голосов
/ 12 мая 2016

Хотя с большими файлами это не совсем эффективно, этот код довольно прост:

  1. Читает объект файла, f.
  2. Разбивает строку, возвращаемую с помощью символов новой строки, \n.
  3. Он получает массивы списков последних индексов, используя знак минуса для обозначения последних индексов, и : для получения подмассива.

    def tail(f,n):
        return "\n".join(f.read().split("\n")[-n:])
    
0 голосов
/ 22 августа 2014
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
...