Obtenez les N dernières lignes d'un fichier avec Python, similaire à tail

j'écris un visualiseur de fichier journal pour une application web et pour cela je veux paginer à travers les lignes du fichier journal. Les éléments dans le fichier sont en ligne avec la nouvelle rubrique sur le fond.

donc j'ai besoin d'une méthode tail() qui peut lire n lignes du bas et soutient un décalage. Ce que j'ai inventé ressemble à ceci:

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

est-ce une approche raisonnable? Quelle est la méthode recommandée pour la queue du journal les fichiers avec des décalages?

155
demandé sur dbr 2008-09-26 01:11:11

28 réponses

c'est peut-être plus rapide que le vôtre. Ne pose aucune hypothèse quant à la longueur de la ligne. Sauvegarde dans le fichier, un bloc à la fois jusqu'à ce qu'il trouve le bon nombre de '\n' personnages.

def tail( f, lines=20 ):
    total_lines_wanted = lines

    BLOCK_SIZE = 1024
    f.seek(0, 2)
    block_end_byte = f.tell()
    lines_to_go = total_lines_wanted
    block_number = -1
    blocks = [] # blocks of size BLOCK_SIZE, in reverse order starting
                # from the end of the file
    while lines_to_go > 0 and block_end_byte > 0:
        if (block_end_byte - BLOCK_SIZE > 0):
            # read the last block we haven't yet read
            f.seek(block_number*BLOCK_SIZE, 2)
            blocks.append(f.read(BLOCK_SIZE))
        else:
            # file too small, start from begining
            f.seek(0,0)
            # only read what was not read
            blocks.append(f.read(block_end_byte))
        lines_found = blocks[-1].count('\n')
        lines_to_go -= lines_found
        block_end_byte -= BLOCK_SIZE
        block_number -= 1
    all_read_text = ''.join(reversed(blocks))
    return '\n'.join(all_read_text.splitlines()[-total_lines_wanted:])

Je n'aime pas les suppositions délicates sur la longueur des lignes quand -- en pratique -- on ne peut jamais savoir des choses comme ça.

Généralement, cela localisera les 20 dernières lignes sur le premier ou le second passage à travers la boucle. Si votre truc de 74 caractères est en fait précis, vous faites la taille du bloc 2048 et vous suivrez 20 lignes presque immédiatement.

en outre, Je ne brûle pas beaucoup de calories du cerveau en essayant de finesse l'alignement avec les blocs physiques OS. En utilisant ces paquets d'e/s de haut niveau, je doute que vous voyiez des conséquences sur les performances en essayant de vous aligner sur les limites des blocs du système D'exploitation. Si vous utilisez des entrées/sorties de niveau inférieur, alors vous pourriez voir une accélération.

113
répondu S.Lott 2014-08-23 20:04:12

suppose un système de type unix sur Python 2 que vous pouvez faire:

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]

pour python 3 vous pouvez faire:

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]
70
répondu Mark 2018-05-10 21:07:59

si la lecture de l'ensemble du fichier est acceptable, utilisez une deque.

from collections import deque
deque(f, maxlen=n)

avant 2.6, deques n'avait pas d'option maxlen, mais c'est assez facile à implémenter.

import itertools
def maxque(items, size):
    items = iter(items)
    q = deque(itertools.islice(items, size))
    for item in items:
        del q[0]
        q.append(item)
    return q

S'il s'agit d'une exigence de lire le fichier à la fin, alors utilisez un galop (A. K. a exponential) search.

def tail(f, n):
    assert n >= 0
    pos, lines = n+1, []
    while len(lines) <= n:
        try:
            f.seek(-pos, 2)
        except IOError:
            f.seek(0)
            break
        finally:
            lines = list(f)
        pos *= 2
    return lines[-n:]
28
répondu A. Coady 2008-11-11 05:17:18

la réponse de S. Lott ci-dessus fonctionne presque pour moi mais finit par me donner des lignes partielles. Il s'avère qu'il corrompt les données sur les limites des blocs parce que les données tiennent les blocs lus dans l'ordre inverse. Lorsque.'' join(données) est appelée, les blocs sont dans le mauvais ordre. Cette correctifs.

def tail(f, window=20):
    """
    Returns the last `window` lines of file `f` as a list.
    """
    if window == 0:
        return []
    BUFSIZ = 1024
    f.seek(0, 2)
    bytes = f.tell()
    size = window + 1
    block = -1
    data = []
    while size > 0 and bytes > 0:
        if bytes - BUFSIZ > 0:
            # Seek back one whole BUFSIZ
            f.seek(block * BUFSIZ, 2)
            # read BUFFER
            data.insert(0, f.read(BUFSIZ))
        else:
            # file too small, start from begining
            f.seek(0,0)
            # only read what was not read
            data.insert(0, f.read(bytes))
        linesFound = data[0].count('\n')
        size -= linesFound
        bytes -= BUFSIZ
        block -= 1
    return ''.join(data).splitlines()[-window:]
25
répondu papercrane 2013-11-08 20:30:09

Voici ma réponse. Pur python. À l'aide de timeit il semble assez rapide. Filing 100 lignes d'un fichier log qui a 100 000 lignes:

>>> timeit.timeit('tail.tail(f, 100, 4098)', 'import tail; f = open("log.txt", "r");', number=10)
0.0014600753784179688
>>> timeit.timeit('tail.tail(f, 100, 4098)', 'import tail; f = open("log.txt", "r");', number=100)
0.00899195671081543
>>> timeit.timeit('tail.tail(f, 100, 4098)', 'import tail; f = open("log.txt", "r");', number=1000)
0.05842900276184082
>>> timeit.timeit('tail.tail(f, 100, 4098)', 'import tail; f = open("log.txt", "r");', number=10000)
0.5394978523254395
>>> timeit.timeit('tail.tail(f, 100, 4098)', 'import tail; f = open("log.txt", "r");', number=100000)
5.377126932144165

voici le code:

import os


def tail(f, lines=1, _buffer=4098):
    """Tail a file and get X lines from the end"""
    # place holder for the lines found
    lines_found = []

    # block counter will be multiplied by buffer
    # to get the block size from the end
    block_counter = -1

    # loop until we find X lines
    while len(lines_found) < lines:
        try:
            f.seek(block_counter * _buffer, os.SEEK_END)
        except IOError:  # either file is too small, or too many lines requested
            f.seek(0)
            lines_found = f.readlines()
            break

        lines_found = f.readlines()

        # we found enough lines, get out
        # Removed this line because it was redundant the while will catch
        # it, I left it for history
        # if len(lines_found) > lines:
        #    break

        # decrement the block counter to get the
        # next X bytes
        block_counter -= 1

    return lines_found[-lines:]
21
répondu glenbot 2017-10-06 14:20:31

le code que j'ai fini par utiliser. Je pense que c'est le meilleur jusqu'à présent:

def tail(f, n, offset=None):
    """Reads a n lines from f with an offset of offset lines.  The return
    value is a tuple in the form ``(lines, has_more)`` where `has_more` is
    an indicator that is `True` if there are more lines in the file.
    """
    avg_line_length = 74
    to_read = n + (offset or 0)

    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], \
                   len(lines) > to_read or pos > 0
        avg_line_length *= 1.3
19
répondu Armin Ronacher 2009-03-28 11:13:44

solution Simple et rapide avec mmap:

import mmap
import os

def tail(filename, n):
    """Returns last n lines from the filename. No exception handling"""
    size = os.path.getsize(filename)
    with open(filename, "rb") as f:
        # for Windows the mmap parameters are different
        fm = mmap.mmap(f.fileno(), 0, mmap.MAP_SHARED, mmap.PROT_READ)
        try:
            for i in xrange(size - 1, -1, -1):
                if fm[i] == '\n':
                    n -= 1
                    if n == -1:
                        break
            return fm[i + 1 if i else 0:].splitlines()
        finally:
            fm.close()
13
répondu dimitri 2011-07-25 09:28:22

j'ai trouvé le Popen ci-dessus pour être la meilleure solution. C'est rapide et sale, et il fonctionne Pour python 2.6 sur Unix machine j'ai utilisé le suivant

    def GetLastNLines(self, n, fileName):
    """
    Name:           Get LastNLines
    Description:        Gets last n lines using Unix tail
    Output:         returns last n lines of a file
    Keyword argument:
    n -- number of last lines to return
    filename -- Name of the file you need to tail into
    """
    p=subprocess.Popen(['tail','-n',str(n),self.__fileName], stdout=subprocess.PIPE)
    soutput,sinput=p.communicate()
    return soutput

le contenu du fichier contient les dernières lignes du code. pour itérer la ligne de production par la ligne faire:

for line in GetLastNLines(50,'myfile.log').split('\n'):
    print line
3
répondu Marko 2012-04-16 13:26:32

une version compatible python3 encore plus propre qui n'insère pas mais ajoute et inverse:

def tail(f, window=1):
    """
    Returns the last `window` lines of file `f` as a list of bytes.
    """
    if window == 0:
        return b''
    BUFSIZE = 1024
    f.seek(0, 2)
    end = f.tell()
    nlines = window + 1
    data = []
    while nlines > 0 and end > 0:
        i = max(0, end - BUFSIZE)
        nread = min(end, BUFSIZE)

        f.seek(i)
        chunk = f.read(nread)
        data.append(chunk)
        nlines -= chunk.count(b'\n')
        end -= nread
    return b'\n'.join(b''.join(reversed(data)).splitlines()[-window:])

utilisez - le comme ceci:

with open(path, 'rb') as f:
    last_lines = tail(f, 3).decode('utf-8')
3
répondu Hauke Rehfeld 2018-01-04 01:54:19

Poster une réponse à la demande des intervenants sur ma réponse à une question similaire où la même technique a été utilisée pour muter la dernière ligne d'un fichier, ne pas l'obtenir.

pour un fichier de taille significative, mmap c'est la meilleure façon de le faire. Pour améliorer la réponse existante mmap , cette version est portable entre Windows et Linux, et devrait fonctionner plus rapidement (bien qu'il ne fonctionnera pas sans certains modifications sur Python 32 bits avec des fichiers dans la gamme GB, voir la autre réponse pour des conseils sur la manipulation de ceci, et pour modifier pour travailler sur Python 2 ).

import io  # Gets consistent version of open for both Py2.7 and Py3.x
import itertools
import mmap

def skip_back_lines(mm, numlines, startidx):
    '''Factored out to simplify handling of n and offset'''
    for _ in itertools.repeat(None, numlines):
        startidx = mm.rfind(b'\n', 0, startidx)
        if startidx < 0:
            break
    return startidx

def tail(f, n, offset=0):
    # Reopen file in binary mode
    with io.open(f.name, 'rb') as binf, mmap.mmap(binf.fileno(), 0, access=mmap.ACCESS_READ) as mm:
        # len(mm) - 1 handles files ending w/newline by getting the prior line
        startofline = skip_back_lines(mm, offset, len(mm) - 1)
        if startofline < 0:
            return []  # Offset lines consumed whole file, nothing to return
            # If using a generator function (yield-ing, see below),
            # this should be a plain return, no empty list

        endoflines = startofline + 1  # Slice end to omit offset lines

        # Find start of lines to capture (add 1 to move from newline to beginning of following line)
        startofline = skip_back_lines(mm, n, startofline) + 1

        # Passing True to splitlines makes it return the list of lines without
        # removing the trailing newline (if any), so list mimics f.readlines()
        return mm[startofline:endoflines].splitlines(True)
        # If Windows style \r\n newlines need to be normalized to \n, and input
        # is ASCII compatible, can normalize newlines with:
        # return mm[startofline:endoflines].replace(os.linesep.encode('ascii'), b'\n').splitlines(True)

cela suppose que le nombre de lignes suivies est suffisamment petit pour que vous puissiez les lire en toute sécurité dans la mémoire à la fois; vous pouvez également en faire une fonction de générateur et lire manuellement une ligne à la fois en remplaçant la ligne finale par:

        mm.seek(startofline)
        # Call mm.readline n times, or until EOF, whichever comes first
        # Python 3.2 and earlier:
        for line in itertools.islice(iter(mm.readline, b''), n):
            yield line

        # 3.3+:
        yield from itertools.islice(iter(mm.readline, b''), n)

enfin, ce lire en mode binaire (nécessaire pour utiliser mmap ) de sorte qu'il donne str lignes (Py2) et bytes lignes (Py3); si vous voulez unicode (Py2) ou str (Py3), l'approche itérative pourrait être modifié pour décoder pour vous et / ou fixer des nouvelles lignes:

        lines = itertools.islice(iter(mm.readline, b''), n)
        if f.encoding:  # Decode if the passed file was opened with a specific encoding
            lines = (line.decode(f.encoding) for line in lines)
        if 'b' not in f.mode:  # Fix line breaks if passed file opened in text mode
            lines = (line.replace(os.linesep, '\n') for line in lines)
        # Python 3.2 and earlier:
        for line in lines:
            yield line
        # 3.3+:
        yield from lines

Note: j'ai tapé tout cela sur une machine où je n'ai pas accès à Python pour tester. S'il vous plaît, faites-moi savoir si j'ai tapé quoi que ce soit; c'était assez similaire à mon autre réponse que je penser il devrait fonctionner, mais les réglages (par exemple, la manipulation d'un offset ) pourrait conduire à de subtiles erreurs. Veuillez me faire savoir s'il y a des erreurs dans les commentaires.

3
répondu ShadowRanger 2018-10-03 17:53:46

basé sur la meilleure réponse de S. Lott (Sep 25 '08 à 21:43), mais corrigé pour les petits fichiers.

def tail(the_file, lines_2find=20):  
    the_file.seek(0, 2)                         #go to end of file
    bytes_in_file = the_file.tell()             
    lines_found, total_bytes_scanned = 0, 0
    while lines_2find+1 > lines_found and bytes_in_file > total_bytes_scanned: 
        byte_block = min(1024, bytes_in_file-total_bytes_scanned)
        the_file.seek(-(byte_block+total_bytes_scanned), 2)
        total_bytes_scanned += byte_block
        lines_found += the_file.read(1024).count('\n')
    the_file.seek(-total_bytes_scanned, 2)
    line_list = list(the_file.readlines())
    return line_list[-lines_2find:]

    #we read at least 21 line breaks from the bottom, block by block for speed
    #21 to ensure we don't get a half line

J'espère que c'est utile.

2
répondu Eyecue 2010-06-10 21:39:02

il existe quelques implémentations de tail sur pypi que vous pouvez installer en utilisant pip:

  • mtFileUtil
  • multitail
  • log4tailer
  • ...

selon votre situation, il peut y avoir des avantages à utiliser l'un de ces outils existants.

2
répondu Travis Bear 2013-09-09 20:12:12

Voici une implémentation assez simple:

with open('/etc/passwd', 'r') as f:
  try:
    f.seek(0,2)
    s = ''
    while s.count('\n') < 11:
      cur = f.tell()
      f.seek((cur - 10))
      s = f.read(10) + s
      f.seek((cur - 10))
    print s
  except Exception as e:
    f.readlines()
2
répondu GL2014 2016-06-19 01:54:08

pour l'efficacité avec des fichiers très volumineux (courant dans les situations de fichier journal où vous pouvez vouloir utiliser tail), vous voulez généralement éviter de lire l'ensemble du fichier (même si vous le faites sans lire l'ensemble du fichier en mémoire à la fois) cependant, vous avez besoin d'une façon ou d'une autre de travailler le décalage en lignes plutôt que des caractères. Une possibilité est de lire à l'envers avec seek () char par char, mais c'est très lent. Au lieu de cela, il est préférable de traiter dans des blocs plus grands.

j'ai un fonction utilitaire j'ai écrit il y a un certain temps pour lire des fichiers à l'envers qui peuvent être utilisés ici.

import os, itertools

def rblocks(f, blocksize=4096):
    """Read file as series of blocks from end of file to start.

    The data itself is in normal order, only the order of the blocks is reversed.
    ie. "hello world" -> ["ld","wor", "lo ", "hel"]
    Note that the file must be opened in binary mode.
    """
    if 'b' not in f.mode.lower():
        raise Exception("File must be opened using binary mode.")
    size = os.stat(f.name).st_size
    fullblocks, lastblock = divmod(size, blocksize)

    # The first(end of file) block will be short, since this leaves 
    # the rest aligned on a blocksize boundary.  This may be more 
    # efficient than having the last (first in file) block be short
    f.seek(-lastblock,2)
    yield f.read(lastblock)

    for i in range(fullblocks-1,-1, -1):
        f.seek(i * blocksize)
        yield f.read(blocksize)

def tail(f, nlines):
    buf = ''
    result = []
    for block in rblocks(f):
        buf = block + buf
        lines = buf.splitlines()

        # Return all lines except the first (since may be partial)
        if lines:
            result.extend(lines[1:]) # First line may not be complete
            if(len(result) >= nlines):
                return result[-nlines:]

            buf = lines[0]

    return ([buf]+result)[-nlines:]


f=open('file_to_tail.txt','rb')
for line in tail(f, 20):
    print line

[Edit] a ajouté une version plus spécifique (évite d'avoir à revenir en arrière deux fois)

1
répondu Brian 2008-09-25 21:51:53

vous pouvez aller à la fin de votre fichier avec F. chercher (0, 2) et ensuite lire les lignes une à une avec le remplacement suivant pour 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
1
répondu rabbit 2010-11-09 07:01:30

basé sur la réponse D'Eyecue (Jun 10 '10 à 21:28): Cette classe ajoute la méthode head() et tail() pour classer l'objet.

class File(file):
    def head(self, lines_2find=1):
        self.seek(0)                            #Rewind file
        return [self.next() for x in xrange(lines_2find)]

    def tail(self, lines_2find=1):  
        self.seek(0, 2)                         #go to end of file
        bytes_in_file = self.tell()             
        lines_found, total_bytes_scanned = 0, 0
        while (lines_2find+1 > lines_found and
               bytes_in_file > total_bytes_scanned): 
            byte_block = min(1024, bytes_in_file-total_bytes_scanned)
            self.seek(-(byte_block+total_bytes_scanned), 2)
            total_bytes_scanned += byte_block
            lines_found += self.read(1024).count('\n')
        self.seek(-total_bytes_scanned, 2)
        line_list = list(self.readlines())
        return line_list[-lines_2find:]

Utilisation:

f = File('path/to/file', 'r')
f.head(3)
f.tail(3)
1
répondu fdb 2011-01-20 19:41:56

plusieurs de ces solutions ont des problèmes si le fichier ne se termine pas dans \n ou en s'assurant que la première ligne complète est lue.

def tail(file, n=1, bs=1024):
    f = open(file)
    f.seek(-1,2)
    l = 1-f.read(1).count('\n') # If file doesn't end in \n, count it anyway.
    B = f.tell()
    while n >= l and B > 0:
            block = min(bs, B)
            B -= block
            f.seek(B, 0)
            l += f.read(block).count('\n')
    f.seek(B, 0)
    l = min(l,n) # discard first (incomplete) line if l > n
    lines = f.readlines()[-l:]
    f.close()
    return lines
1
répondu David Rogers 2011-04-12 16:14:42

mise à Jour @papercrane solution pour python3. Ouvrir le fichier avec open(filename, 'rb') et:

def tail(f, window=20):
    """Returns the last `window` lines of file `f` as a list.
    """
    if window == 0:
        return []

    BUFSIZ = 1024
    f.seek(0, 2)
    remaining_bytes = f.tell()
    size = window + 1
    block = -1
    data = []

    while size > 0 and remaining_bytes > 0:
        if remaining_bytes - BUFSIZ > 0:
            # Seek back one whole BUFSIZ
            f.seek(block * BUFSIZ, 2)
            # read BUFFER
            bunch = f.read(BUFSIZ)
        else:
            # file too small, start from beginning
            f.seek(0, 0)
            # only read what was not read
            bunch = f.read(remaining_bytes)

        bunch = bunch.decode('utf-8')
        data.insert(0, bunch)
        size -= bunch.count('\n')
        remaining_bytes -= BUFSIZ
        block -= 1

    return ''.join(data).splitlines()[-window:]
1
répondu Emilio 2017-08-30 12:40:01

j'ai dû lire une valeur spécifique de la dernière ligne d'un fichier, et je suis tombé sur ce fil. Plutôt que de réinventer la roue en Python, j'ai fini avec un petit script shell, /usr / local / bin/get_last_netp:

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

et dans le programme Python:

from subprocess import check_output

last_netp = int(check_output("/usr/local/bin/get_last_netp"))
0
répondu Leifbk 2013-05-12 12:11:01

pas le premier exemple utilisant une deque, mais un plus simple. Celui-ci est général: il fonctionne sur n'importe quel objet itérable, pas seulement un fichier.

#!/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
répondu Hal Canary 2013-05-12 12:38:55
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
répondu Raj 2014-04-25 10:24:36
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
répondu moylop260 2014-08-22 15:52:53
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
répondu Y Kal 2018-03-03 21:54:03
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
répondu Kant Manapure 2018-06-17 06:40:53

j'ai trouvé un moyen probablement le plus facile de trouver le premier ou le dernier N Lignes d'un fichier""

dernières lignes D'un fichier(pour Ex:N=10)

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

premières lignes D'un fichier (pour Ex:N=10)

file=open("xyz.txt",'r")
liner=file.readlines()
for ran in range(0,N+1):
    print liner[ran]
0
répondu user9956608 2018-06-18 12:03:11

en y repensant, c'est probablement aussi rapide que n'importe quoi ici.

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]

C'est beaucoup plus simple. Et il semble se déchirer à un bon rythme.

-1
répondu S.Lott 2008-09-25 22:03:09

c'est si simple:

def tail(fname,nl):
with open(fname) as f:
    data=f.readlines() #readlines return a list
    print(''.join(data[-nl:]))
-1
répondu Med sadek 2018-06-20 11:49:34

bien que ce ne soit pas vraiment du côté efficace avec les gros fichiers, ce code est assez simple:

  1. Il lit le fichier d'objet, f .
  2. il divise la chaîne retournée en utilisant newlines, \n .
  3. il obtient le tableau listes derniers index, en utilisant le signe négatif pour représenter les derniers index, et le : pour obtenir un subarray.



    def tail(f,n):
        return "\n".join(f.read().split("\n")[-n:])
    
-3
répondu ProgramFast 2016-05-12 02:57:48