2014-12-20 14 views
5

Una delle modifiche in python 3 è stata quella di rimuovere la possibilità di cercare dalla fine del file in modalità testo normale. Qual è l'alternativa generalmente accettata a questo?Cerca dalla fine del file in python 3

Per esempio in python 2.7 sarei entrato file.seek (-3,2)

Ho letto un po 'sul perché hanno fatto questo quindi per favore non solo un collegamento a un PEP. So che usare 'rb' mi permetterebbe di cercare, ma questo rende il mio file di testo letto nel formato sbagliato.

+0

Per codifiche a byte singolo è sempre possibile decodificare i dati manualmente. –

+0

https://docs.python.org/3.1/tutorial/inputoutput.html se si utilizza python 3.1 seek è ancora disponibile –

+0

@IsuruMadusanka: seek è disponibile in tutte le versioni di Python 3. Ciò che non è disponibile è ** cercare un parente alla fine **. 3.1 non fa eccezione. –

risposta

5

In Python 2, i dati del file non venivano decodificati durante la lettura. La ricerca di codifiche all'indietro e multibyte non si confonde bene (non è possibile sapere dove verrà avviato il prossimo carattere), motivo per cui è disabilitato per Python 3.

È ancora possibile cercare sul buffer sottostante oggetto, tramite la TextIOBase.buffer attribute, ma poi si dovrà riattaccare un nuovo TextIOBase involucro, come il wrapper attuale non è più saprà dove si trova in:

import io 

file.buffer.seek(-3, 2) 
file = io.TextIOWrapper(
    file.buffer, encoding=file.encoding, errors=file.errors, 
    newline=file.newlines) 

ho copiato attraverso qualsiasi codifica e la linea gestione delle informazioni su io.TextIOWrapper() object.

Prendere in considerazione che questo può decodificare potrebbe rompere per UTF-16, UTF-32, UTF-8 e altri codec multi-byte.

Demo:

>>> import io 
>>> with open('demo.txt', 'w') as out: 
...  out.write('Demonstration\nfor seeking from the end') 
... 
38 
>>> with open('demo.txt') as inf: 
...  print(inf.readline()) 
...  inf.buffer.seek(-3, 2) 
...  inf = io.TextIOWrapper(inf.buffer) 
...  print(inf.readline()) 
... 
Demonstration 

35 
end 

Si potrebbe avvolgere questo in una funzione di utilità:

import io 

def textio_seek(fobj, amount, whence=0): 
    fobj.buffer.seek(amount, whence) 
    return io.TextIOWrapper(
     fobj.buffer, encoding=fobj.encoding, errors=fobj.errors, 
     newline=fobj.newlines) 

e usare questo come:

with open(somefile) as file: 
    # ... 

    file = textio_seek(file, -2, 3) 

    # ... 

Utilizzando l'oggetto file come un contesto responsabile solo funziona ancora, come l'oggetto file originale si riferisce ence è ancora collegato all'oggetto buffer del file originale e quindi può ancora essere utilizzato per chiudere il file.