SORU
25 EYLÜL 2008, PERŞEMBE


Python, kuyruğa benzer bir dosyanın son n çizgiler

Bir web uygulaması için günlük dosyası görüntüleyici yazıyorum ve bunun için günlük dosyası satırlarını üzerinden ilerlemek istiyorum. Dosyasındaki öğeler altında yeni bir madde ile temel çizgi vardır.

Alttan n satır okuyabilen tail() bir yöntem istiyorum ve bir ofset destekler. Ne buldum bu gibi görünüyor:

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

Bu mantıklı bir yaklaşım mı? Uzaklıklar ile kuyruk günlük dosyaları için önerilen yol nedir?

CEVAP
25 EYLÜL 2008, PERŞEMBE


Bu senin daha hızlı olabilir. Satır uzunluğu hakkında herhangi bir varsayımda bulunmaz. Dosya üzerinden sırtlarına doğru numarayı buldum kadar bir defada bir blok '\n' karakterleri.

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:])

Pratik bir mesele olarak asla böyle şeyler biliyorsunuz zaman satır uzunluğu hakkında yanıltıcı varsayımlar sevmiyorum.

Genel olarak, bu döngü ilk veya ikinci geçişte son 20 satırı bulun. Eğer 74 karakter şey gerçekten doğru ise, blok boyutu 2048 yapmak ve 20 hatları hemen kuyruk.

Ayrıca, beyin kalori fiziksel OS blokları ile uyum incelik için çalışıyor yakmak istemiyorum. Üst düzey Bu G/Ç paketleri kullanarak, OS blok sınırlarına hizalamak için çalışırken herhangi bir performans sonucu göreceğinden şüpheliyim. Eğer alt düzey G/Ç kullanırsanız, daha sonra bir hızlanma görebilirsiniz.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Benjamin Heckendorn

    Benjamin Hec

    4 Mayıs 2008
  • Canceriansoul

    Canceriansou

    15 Ocak 2011
  • Madeon

    Madeon

    31 Ocak 2010