linecache - Leggere con efficacia i file di testo

Scopo Recupera righe di testo da file o da moduli python importati, mantenendo una cache dei risultati per rendere la lettura di molte righe dallo stesso file più efficiente.
Versione Python 1.4

Il modulo linecache viene usato estensivamente attraverso la libreria standard di Python quando occorre trattare file sorgente di Python. L'implementazione della cache mantiene semplicemente il contenuto dei file, elaborati in righe separate, in un dizionario in memoria. L'API restituisce le righe richieste indicizzate in una lista. Il tempo risparmiato è quello che occorrerebbe per leggere (ripetutamente) il file ed elaborare le righe per trovare quella richiesta. Questo è particolarmente utile quando occorre trovare righe multiple nello stesso file, come ad esempio per produrre una traccia dello stack per una rapporto di errore.

Dati per il Test

Si usa del testo prodotto dal generatore Lorem Ipsum come input di esempio.

import os
import tempfile

lorem = '''Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Vivamus eget elit. In posuere mi non risus. Mauris id quam posuere
lectus sollicitudin varius. Praesent at mi. Nunc eu velit. Sed augue
massa, fermentum id, nonummy a, nonummy sit amet, ligula. Curabitur
eros pede, egestas at, ultricies ac, pellentesque eu, tellus.

Sed sed odio sed mi luctus mollis. Integer et nulla ac augue convallis
accumsan. Ut felis. Donec lectus sapien, elementum nec, condimentum ac,
interdum non, tellus. Aenean viverra, mauris vehicula semper porttitor,
ipsum odio consectetuer lorem, ac imperdiet eros odio a sapien. Nulla
mauris tellus, aliquam non, egestas a, nonummy et, erat. Vivamus
sagittis porttitor eros.'''

def make_tempfile():
    fd, temp_file_name = tempfile.mkstemp()
    os.close(fd)
    f = open(temp_file_name, 'wt')
    try:
        f.write(lorem)
    finally:
        f.close()
    return temp_file_name

def cleanup(filename):
    os.unlink(filename)

Leggere Righe Specifiche

Per leggere la quinta riga dal file basta una riga di codice. Si noti che i numeri di riga nel modulo linecache iniziano da 1, ma se le righe vengono divise tramite codice l'array viene indicizzato a partire da 0. Occorre anche eliminare il carattere di ritorno a capo a fine riga restituito dalla cache.

import linecache
from linecache_data import *

filename = make_tempfile()

# Estrazione della stessa riga dalla sorgente e dalla cache.
# (Notare che linecache conta da 1)
print 'SORGENTE: ', lorem.split('\n')[4]
print 'CACHE   : ', linecache.getline(filename, 5).rstrip()

cleanup(filename)
$ python linecache_getline.py

SORGENTE:  eros pede, egestas at, ultricies ac, pellentesque eu, tellus.
CACHE   :  eros pede, egestas at, ultricies ac, pellentesque eu, tellus.

Gestire le Righe Vuote

Ecco cosa accade se la riga desiderata è vuota:

import linecache
from linecache_data import *

filename = make_tempfile()

# Le righe vuote includono un ritorno a capo
print '\nVUOTA : "%s"' % linecache.getline(filename, 6)

cleanup(filename)
$ python linecache_out_of_range.py

VUOTA : "
"

Gestire gli Errori

Se il numero della riga richiesta è fuori dall'intervallo delle righe valide nel file, linecache ritorna una stringa vuota.

import linecache
from linecache_data import *

filename = make_tempfile()

# La cache ritorna sempre una stringa, ed usa
# una stringa vuota per indicare una riga che
# non esiste.
non_qui = linecache.getline(filename, 500)
print "\nNON QUI: '%s' comprende %d caratteri" %  (non_qui, len(non_qui))

cleanup(filename)
$ python linecache_empty_line.py

NON QUI: '' comprende 0 caratteri

Il modulo non solleva mai una eccezione, anche se il file non esiste:

import linecache

# Gli errori sono nascosti anche se linecache non trova il file
no_such_file = linecache.getline('this_file_does_not_exist.txt', 1)
print '\nNESSUN FILE: ', no_such_file
$ python linecache_missing_file.py

NESSUN FILE:

Sorgenti Python

Visto che linecache viene usato così frequentemente per produrre tracce dello stack, una della caratteristiche chiave è la capacità di trovare i sorgenti dei moduli Python inclusi in sys.path specificando il nome base del modulo. Il codice che serve per riempire la cache in linecache cerca il modulo in sys.path se non riesce a trovare il file direttamente.

import linecache

# Cerca il modulo linecache, usando
# la ricerca built-in in sys.path
module_line = linecache.getline('linecache.py', 3)
print '\nMODULO : ', module_line
$ python linecache_path_search.py

MODULO :  This is intended to read lines from modules imported -- hence if a filename

Vedere anche:

linecache
La documentazione della libreria standard per questo modulo.
http://www.ipsum.com
Il generatore Lorem Ipsum.