Può cercare e raccontare il lavoro con i documenti codifica UTF-8 in Python?
Domanda
Ho un'applicazione che genera alcuni file di log di grandi dimensioni> 500MB.
ho scritto alcune utility in Python che mi permette di navigare velocemente nel file di registro e di trovare i dati di interesse. Ma io ora ottenere alcuni insiemi di dati in cui il file è troppo grande per caricare tutto in memoria.
Ho dunque desidera eseguire la scansione del documento, una volta, costruire un indice e quindi caricare solo la sezione del documento in memoria che io voglio guardare alla volta.
Questo funziona per me, quando apro un 'file' leggere una riga alla volta e memorizzare l'offset con da file.tell (). Posso poi tornare a quella sezione del file in seguito con file.seek (offset, 0).
Il mio problema è, tuttavia, che io possa avere UTF-8 nei file di log quindi ho bisogno di aprirli con il modulo codecs (codecs.open(<filename>, 'r', 'utf-8')
). Con l'oggetto risultante posso chiamare cercare e raccontare, ma che non corrispondono.
Suppongo che codec deve fare un po 'di buffering o forse restituisce il carattere conta invece di byte da dire?
C'è un modo per aggirare questo?
Soluzione
Se fosse vero, questo suona come un insetto o la limitazione del modulo codecs, come è scostamenti di byte e caratteri probabilmente confuse.
Vorrei utilizzare la funzione open()
regolare per l'apertura del file, quindi seek()
/ tell()
vi darà Byte offset che sono sempre coerenti. Ogni volta che si desidera leggere, utilizzare f.readline().decode('utf-8')
.
Attenzione, però, che utilizza la funzione f.read()
si può atterrare nel bel mezzo di un carattere multi-byte, producendo così un errore di decodifica UTF-8. readline()
funzionerà sempre.
Questa non trasparente gestisce il marchio di byte-ordine per te, ma è probabile che i file di log non hanno distinte base in ogni caso.
Altri suggerimenti
Per UTF-8, non è effettivamente bisogno di aprire il file con codecs.open. Invece, è affidabile per leggere il file come stringa di byte prima, e solo allora decodificare un singola sezione (richiamando il metodo .decode sulla stringa). Rompere il file all'ultima riga è sicuro; l'unico modo non sicuro per dividere, sarebbe nel bel mezzo di un carattere multi-byte (che si può riconoscere dal suo valore di byte> 128).
Molto di ciò che accade con UTF8 in Python ha un senso se si guarda a come è stato fatto in Python 3. Nel tuo caso, si farà un po 'più senso se leggete il capitolo file in Dive Into Python 3 : http://diveintopython3.org/files.html
Il corto di esso, però, è che file.seek
e file.tell
lavoro con posizioni di byte, mentre i caratteri Unicode possono occupare più byte. Quindi, se si fa:
f.seek(10)
f.read(1)
f.tell()
Si può facilmente ottenere qualcosa di diverso da 17
, a seconda di cosa lunghezza di un carattere si legge era.
Update: Non si può fare cercare / dire sull'oggetto restituito da codec.open (). È necessario utilizzare un file normale, e decodificare le stringhe a unicode dopo la lettura.
Non so il motivo per cui non funziona, ma non riesco a farlo funzionare. La cercano sembra funzionare solo una volta, per esempio. Allora avete bisogno di chiudere e riaprire il file, che è, naturalmente, non è utile.
Il tell non usa posizioni dei caratteri, ma non mostra dove la vostra posizione nel flusso è (ma probabilmente in cui l'oggetto file sottostante è nella lettura dal disco).
Quindi, probabilmente a causa di una sorta di buffer di fondo, non si può fare. Ma dopo aver letto deocding funziona bene, in modo da andare per questo.