2012-12-02 16 views
16

Sto riscontrando un problema con Python string.format() e il passaggio di stringhe Unicode. È simile a this older question, con la differenza che nel mio caso il codice di prova esplode sulla stampa, non sulla chiamata logging.info(). Il passaggio dello stesso oggetto stringa Unicode a un gestore di registrazione funziona correttamente.Python's string.format() e Unicode

Ciò non funziona altrettanto bene con la precedente formattazione % e string.format(). Per accertarmi che fosse l'oggetto stringa il problema, e non stampare interagendo male con il mio terminale, ho provato ad assegnare la stringa formattata a una variabile prima della stampa.

def unicode_test(): 
    byte_string = '\xc3\xb4' 
    unicode_string = unicode(byte_string, "utf-8") 
    print "unicode object type: {}".format(type(unicode_string)) 
    output_string = "printed unicode object: {}".format(unicode_string) 
    print output_string 

if __name__ == '__main__': 
    unicode_test() 

L'oggetto stringa sembra presupporre che ottenga ASCII.

% python -V 
Python 2.7.2 

% python ./unicodetest.py 
unicode object type: <type 'unicode'> 
Traceback (most recent call last): 
    File "./unicodetest.py", line 10, in <module> 
    unicode_test() 
    File "./unicodetest.py", line 6, in unicode_test 
    output_string = "printed unicode object: {}".format(unicode_string) 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf4' in position 0: ordinal not in range(128) 

Cercando di lanciare output_string come Unicode non fa alcuna differenza.

output_string = u "oggetto stampato unicode: {}". Formato (UNICODE_STRING)

mi manca qualcosa qui? La documentazione per l'oggetto stringa sembra abbastanza chiara che questo dovrebbe funzionare mentre sto tentando di usarlo.

+0

L'utilizzo del codice come sopra, ma l'esecuzione di un 'oggetto Unicode stampato' con 'u' funziona per me (Python 2.6.5 e 2.7). L'errore che stai ricevendo quando lo fai è lo stesso sopra elencato? – RocketDonkey

+0

Attendi ... stai codificando un flusso di byte unicode che dovrebbe rappresentare uno stream unicode già codificato? Quale personaggio deve stampare sopra per ''\ xc3 \ xb4'':' ô' o 'Ã''? –

+0

Dovrebbe essere ô. L'esempio di codifica è stato copiato in modo abbastanza dettagliato dal post precedente di riferimento sul modulo di registrazione. – mpounsett

risposta

22

No, questo non dovrebbe funzionare (puoi citare la parte della documentazione che dice così?), Ma dovrebbe funzionare se il modello di formattazione è unicode (o con la vecchia formattazione che "promuove" il pattern in Unicode invece di cercando di "abbassare" gli argomenti).

>>> x = "\xc3\xb4".decode('utf-8') 
>>> x 
u'\xf4' 
>>> x + 'a' 
u'\xf4a' 
>>> 'a' + x 
u'a\xf4' 
>>> 'a %s' % x 
u'a \xf4' 
>>> 'a {}'.format(x) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec 
    can't encode character u'\xf4' in position 0: ordinal not in range(128) 
>>> u'a {}'.format(x) 
u'a \xf4' 
>>> print u"Foo bar {}".format(x) 
Foo bar ô 

Edit: La linea print potrebbe non funzionare per voi, se la stringa unicode non può essere codificato utilizzando la codifica della console. Ad esempio, sulla mia console Windows:

>>> import sys 
>>> sys.stdout.encoding 
'cp852' 
>>> u'\xf4'.encode('cp852') 
'\x93' 

Su una console UNIX questo potrebbe essere correlato alle impostazioni locali. Fallirà anche se si reindirizza l'output (come quando si utilizza | nella shell). La maggior parte di questi problemi sono stati risolti in Python 3.

+0

@mpounsett: Bene, come potete vedere nella sessione della console che ho postato, 'u'Whatever {} '. Format (u' \ xf4 ')' funziona, quindi potresti voler ricontrollare il tuo codice. L'errore è esattamente lo stesso? Accade nella stessa linea o è più simile a: http://ideone.com/Z3y5Kg? – lqc

+0

Hrm .. Avevo pensato che l'errore fosse esattamente lo stesso, ma su un ricontrollo vedo che in realtà migra alla dichiarazione di stampa. – mpounsett