2009-05-27 18 views
7

Qualcuno può spiegare a me questa cosa strana:Python unicode in Mac terminale OS X

Quando nel guscio di pitone ho digitare la seguente stringa Cirillico:

>>> print 'абвгд' 
абвгд 

ma quando digito:

>>> print u'абвгд' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-9: ordinal not in range(128) 

Dal momento che il primo tring è uscito correttamente, ritengo che il mio terminale OS X possa rappresentare unicode, ma si scopre che non può nel secondo caso. Perché ?

risposta

16
>>> print 'абвгд' 
абвгд 

Quando si digitano alcuni caratteri, il terminale decide come questi caratteri vengono rappresentati nell'applicazione. Il tuo terminale potrebbe dare i caratteri all'applicazione codificata come utf-8, ISO-8859-5 o anche qualcosa che solo il tuo terminale capisce. Python ottiene questi caratteri come una sequenza di byte. Quindi python stampa questi byte così come sono e il tuo terminale li interpreta in qualche modo per visualizzare i caratteri. Dal momento che il terminale di solito interpreta i byte allo stesso modo in quanto codificato loro prima, tutto è visualizzato come digitato in.

>>> u'абвгд' 

Qui si digita alcuni caratteri che arrivano al l'interprete Python come una sequenza di byte, forse codificato in qualche modo dal terminale. Con il prefisso u python tenta di convertire questi dati in unicode. Per farlo correttamente Python deve sapere quale codifica utilizza il tuo terminale. Nel tuo caso sembra che Python pensi che la codifica dei tuoi terminali sia ASCII, ma i dati ricevuti non corrispondono a quelli, quindi ottieni un errore di codifica.

Il modo dritto in avanti per creare stringhe Unicode in una sessione interattiva sarebbe quindi essere qualcosa di simile a questo:

>>> us = 'абвгд'.decode('my-terminal-encoding') 

Nei file è anche possibile specificare la codifica del file con una linea speciale modalità:

# -*- encoding: ISO-8859-5 -*- 
us = u'абвгд' 

Per altri modi per impostare la codifica di input predefinita è possibile consultare sys.setdefaultencoding(...) o sys.stdin.encoding.

+0

Sì, questo ha molto senso per me, grazie. – disc0dancer

+0

+1 risposta molto completa –

0

Un oggetto unicode deve essere codificato prima di poter essere visualizzato su alcune console. Prova

u'абвгд'.encode() 

invece per codificare i unicode a un oggetto stringa (molto probabilmente utilizzando utf8 come codifica di default, ma dipende dal vostro config pitone)

+0

questo non sta funzionando - encode() genera lo stesso errore. – disc0dancer

3

Inoltre, assicurarsi che la codifica del terminale è impostata su Unicode/UTF-8 (e non ASCII, che sembra essere l'impostazione):

http://www.rift.dk/news.php?item.7.6

+0

L'ho capito, ma quello che mi infastidisce è che il mio terminale mostra unicode correttamente se è stato digitato come una stringa normale - ad es. 'уникоде', ma genera un errore se provo a stampare la stessa stringa di u'уникоде ' – disc0dancer

9

Oltre a garantire il terminale di OS X è impostato su UTF-8, si potrebbe desiderare di impostare la codifica sys predefinita python a UTF-8 o migliore. Creare un file in /Library/Python/2.5/site-packages chiamato sitecustomize.py. In questo file messo:

import sys 
sys.setdefaultencoding('utf-8') 

Il metodo setdefaultencoding è disponibile solo dal modulo del sito, e viene rimosso dal sys namespace once startup has completed. Pertanto, è necessario avviare un nuovo interprete Python affinché le modifiche abbiano effetto. È possibile verificare la codifica predefinita corrente in qualsiasi momento dopo l'avvio con sys.getdefaultencoding().

Se i caratteri non sono già unicode e avete bisogno di convertirli, utilizzare il metodo decode su una stringa per decodificare il testo da un altro set di caratteri unicode in ... meglio specificare che charset:

s = 'абвгд'.decode('some_cyrillic_charset') # makes the string unicode 
print s.encode('utf-8') # transform the unicode into utf-8, then print it 
+0

Questo ha risolto i miei problemi, sebbene la spiegazione repr() non sia corretta. Ho fatto un errore nella mia domanda (mi dispiace), che ora ho risolto: stavo stampando la stringa u'абвгd in realtà, quindi non è un errore repr(). In effetti, non ottengo l'errore se ometto l'istruzione di stampa - Ho appena ottenuto '\ xd0 \ xb0 \ xd0 \ xb1 \ xd0 \ xb2 \ xd0 \ xb3 \ xd0 \ xb4' La mia ipotesi sarebbe che la codifica predefinita - mac-romana è in qualche modo in grado di rappresentare i caratteri cirillici (che, d'altra parte, non aveva senso ...), ma non in cirillico in unicode. Davvero non capisco questo :) – disc0dancer

+0

Grazie per il discodancer di informazioni ... hai ragione ... il mio male. –

+0

Non modificare la codifica predefinita del sistema; correggi invece i tuoi valori Unicode. La modifica della codifica predefinita può rompere le librerie che si basano sul comportamento predefinito *. C'è un motivo per cui devi forzare il caricamento di un modulo prima di poterlo fare. –

0

'абвгд' non è una stringa unicode

u'абвгд' è una stringa unicode

Non è possibile stampare le stringhe Unicode senza di loro codifica. Quando hai a che fare con stringhe nella tua applicazione, vuoi assicurarti che ogni input sia decodificato e qualsiasi output in codificato. In questo modo la tua applicazione gestirà solo stringhe unicode internamente e produrrà stringhe in UTF8.

Per riferimento:

>>> 'абвгд'.decode('utf8') == u'абвгд' 
>>> True 
13

Come di Python 2.6, è possibile utilizzare la variabile di ambiente PYTHONIOENCODING dire Python che il vostro terminale è UTF-8 capace. Il modo più semplice per fare questo permanente è aggiungendo la seguente riga al ~/.bash_profile:

export PYTHONIOENCODING=utf-8 

Terminal.app showing unicode output from Python

+0

Grazie, ha reso la mia giornata! – bouke

+0

Un bell'esempio, soprattutto considerando che la build di python per OSX è disponibile con 'sys.maxunicode == 0xffff' magro –

+0

Ho avuto problemi con sympy pretty print e il tuo trucco ha risolto il problema. Grazie. – Pouya