2013-05-14 12 views
19

Durante il porting di codice da Python 2 a Python 3, mi imbatto in questo problema durante la lettura del testo UTF-8 dallo standard input. In Python 2, questo funziona bene:Python 3: Come specificare la codifica stdin

for line in sys.stdin: 
    ... 

Ma Python 3 si aspetta da ASCII sys.stdin, e se ci sono caratteri non-ASCII in ingresso, ottengo l'errore:

UnicodeDecodeError: 'ascii' codec can't decode byte .. in position ..: ordinal not in range(128)

per un file regolare, vorrei specificare la codifica all'apertura del file:

with open('filename', 'r', encoding='utf-8') as file: 
    for line in file: 
     ... 

Ma come posso specificare la codifica standard input? Altri post SO hanno suggerito di utilizzare

input_stream = codecs.getreader('utf-8')(sys.stdin) 
for line in input_stream: 
    ... 

Tuttavia, questo non funziona in Python 3. Ricevo ancora lo stesso messaggio di errore. Sto usando Ubuntu 12.04.2 e il mio locale è impostato su en_US.UTF-8.

risposta

35

Python 3 fa non prevede ASCII da sys.stdin. Aprirà stdin in modalità testo e farà un'ipotesi plausibile su quale codifica venga utilizzata. Questa ipotesi potrebbe arrivare a ASCII, ma non è un dato. Vedi lo sys.stdin documentation su come è stato selezionato il codec.

Come altri oggetti di file aperti in modalità testo, l'oggetto sys.stdin deriva da io.TextIOBase base class; ha un attributo .buffer che punta all'istanza IO bufferizzata sottostante (che a sua volta ha un attributo .raw).

Wrap l'attributo sys.stdin.buffer in una nuova io.TextIOWrapper() instance per specificare una codifica diversa:

import io 
import sys 

input_stream = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8') 

alternativa, impostare il PYTHONIOENCODING environment variable al codec desiderato durante l'esecuzione pitone.

+0

Grazie, questo ha fatto il trucco! –

+2

Qual è l'equivalente più vicino per python2.6? – bukzor

+1

@bukzor: opzione successiva: apre il descrittore di file direttamente con 'io.open()'; '0' è' stdin': 'io.open (0)' restituisce un oggetto 'TextIOWrapper()'. –