2012-04-17 19 views
9

Voglio usare un flusso bufferizzato perché voglio usare un metodo peek() per sbirciare in avanti ma usare il mio flusso con un altro metodo che si aspetta un oggetto simile a un file. (Userei seek() ma può avere per gestire in filodiffusione-in I/O che non supporta l'accesso casuale.)python: usando io.BufferedReader su uno stream ottenuto con open()?

Ma questo banco di prova fallisce:

AttributeError: 'file' oggetto non ha attributo ' _checkReadable'

import sys 
import io 

srcfile = sys.argv[1] 
with open(srcfile, 'rb') as f: 
    fbuf = io.BufferedReader(f) 
    print fbuf.read(20) 

che cosa sta succedendo e come posso risolvere il problema? Pensavo che BufferedReader avesse lo scopo di bufferizzare un flusso. In tal caso, perché la funzione open() non restituisce qualcosa che sia compatibile con esso?

+0

E 'interessante. Anche se abbiamo le stesse versioni (2.7.x), otteniamo messaggi di errore leggermente diversi. – username

+0

L'ho scoperto. C'è un commento in io.py come "" "Le descrizioni dei metodi e le implementazioni predefinite sono ereditate dalla versione C." "Quindi dipende dalle versioni c o dal sistema operativo. – username

+0

@username: non è specifico per il sistema operativo. My Python 2.6.7 si lamenta anche di '_checkReadable', mentre il mio 2.7.2 si lamenta di' readable'.Non riesco a trovare il commit in questo momento, ma questo probabilmente è stato cambiato da qualche parte tra 2.7.0 e 2.7.2. –

risposta

1

È possibile impostare la quantità di buffer in byte passando il buffering argument per aprire:

import sys 

srcfile = sys.argv[1] 
with open(srcfile, 'rb', buffering=30) as f: 
    print(f.peek(30)) 
    print(f.read(20)) 

Questa è una BufferedReader:

>>> with open("test.txt", 'rb', buffering=30) as f: 
...  type(f) 
<class '_io.BufferedReader'> 

Si noti che, per impostazione predefinita, è tamponata a 1 - linea bufferizzata.

+0

sicuro, va bene , ma alla fine mi viene voglia di bufferizzare attorno ad altre fonti di input che potrebbero non essere bufferizzate ... o è tutto semplicemente bufferizzato di default? sys.stdin? flussi di rete? –

+0

Bene, allora puoi fare ciò che hai fatto e fatto "BufferedReader (f)" - poiché è già un "BufferedReader" funzionerà. –

+1

Questa è la soluzione Python 3; in Python 2 l'OP dovrebbe usare 'io.open'. –

15

Con il look del vostro print dichiarazione, si sta utilizzando Python 2. In quella versione, un file non è un argomento valido per il costruttore BufferedReader:

Under Python 2.x, this is proposed as an alternative to the built-in file object, but in Python 3.x it is the default interface to access files and streams. (1)

si dovrebbe usare io.open invece:

>>> f = io.open(".bashrc", "rb") 

Se si esegue questa operazione, non c'è bisogno di avvolgere in modo esplicito in un BufferedReader dato che questo è esattamente ciò che io.open restituisce per impostazione predefinita:

>>> type(f) 
<type '_io.BufferedReader'> 

Vedere its docs per dettagli; c'è un argomento buffering che controlla il buffering.

In Python 3, open is io.open quindi le due librerie di I/O sono state unite in una. Sembra che io sia stato aggiunto a Python 2.6 principalmente per compatibilità diretta.

+0

+1: questa è la risposta corretta per 2.x –

+1

non è necessario avvolgere per aprire un file, ma cosa succede se uso sys.stdin invece? –

+0

@JasonS: quindi [hack] (http://stackoverflow.com/questions/6065173/making-io-bufferedreader-from-sys-stdin-in-python) a cui è stato indicato 'username' è valido. O 'io.open ("/dev/stdin ")' se la tua piattaforma ha quel file (ma in entrambi i casi stai lontano da 'sys.stdin'). –

0

In python2, se si deve utilizzare file oggetto come restituito da open (o ad esempio fornito da alcune routine del modulo che non è possibile modificare), è possibile utilizzare il descrittore di file ottenuto dalla fileno() per io.FileIO costruttore, quindi passare io.FileIO oggetto da io.BufferedReader costruttore.

Quindi, è esempio di codice può essere riscritta come segue:

import sys 
import io 

srcfile = sys.argv[1] 
with open(srcfile, 'rb') as f: 
    fio = io.FileIO(f.fileno()) 
    fbuf = io.BufferedReader(fio) 
    print fbuf.read(20) 
Problemi correlati