2012-12-02 13 views
16

Mam problem z string.format() Pythona i przekazywanie do niego ciągów Unicode. Jest to podobne do this older question, z tym że w moim przypadku kod testowy wybucha na wydruku, a nie na wywołaniu logging.info(). Przekazywanie tego samego obiektu napisowego Unicode do obsługi rejestrowania działa dobrze.Python's string.format() i Unicode

Nie powiedzie się równie dobrze ze starszym formatem %, jak i string.format(). Aby upewnić się, że jest to obiekt typu string, który jest problemem, a nie drukowanie źle współpracujące z moim terminalem, próbowałem przypisać sformatowany ciąg do zmiennej przed drukowaniem.

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() 

Obiekt tekstowy wydaje się zakładać, że otrzymuje 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) 

Próbujesz rzucić output_string, ponieważ Unicode nie robi żadnej różnicy.

output_string = u "drukowany obiekt unicode: {}". Format (unicode_string)

Am I brakuje czegoś tutaj? Dokumentacja obiektu typu string wydaje się całkiem jasna, że ​​to powinno działać tak, jak próbuję go użyć.

+0

Użycie kodu jak powyżej, ale kontynuacja 'drukowanego obiektu unicode' z' u' działa dla mnie (Python 2.6.5 i 2.7). Czy błąd pojawia się, gdy robisz to samo, co wymienione powyżej? – RocketDonkey

+0

Czekaj ... kodujesz strumień bajtów Unicode, który ma reprezentować już zakodowany strumień Unicode? Jaki znak powinien zostać wydrukowany powyżej dla ''\ xc3 \ xb4'':' ô' lub 'Ã''? –

+0

Powinno to być ô. Przykład kodowania został skopiowany dosłownie z przywołanego starszego posta o module logowania. – mpounsett

Odpowiedz

22

Nie, to nie powinno działać (czy można przytoczyć część dokumentacji, która tak mówi?), Ale powinno działać, jeśli wzór formatowania jest w Unicode (lub ze starym formatowaniem, które "promuje" wzorzec do unicodu zamiast próbuje "zdegradować" argumenty).

>>> 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: Linia print nie może pracować dla Ciebie, jeśli ciąg Unicode nie mogą być kodowane przy użyciu kodowania swojej konsoli. Na przykład na mojej konsoli Windows:

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

Na konsoli systemu UNIX może to być związane z ustawieniami narodowymi. To również się nie powiedzie, jeśli przekierujesz dane wyjściowe (np. Gdy używasz powłoki |). Większość z tych problemów została naprawiona w Pythonie 3.

+0

@mpounsett: Cóż, jak widać w sesji konsoli napisałem, "u'Whatever {}" .format (u '\ xf4') działa, więc możesz sprawdzić swój kod. Czy błąd jest dokładnie taki sam? Czy dzieje się to w tej samej linii, czy jest bardziej podobny: http://ideone.com/Z3y5Kg? – lqc

+0

Hrm .. Myślałem, że błąd był dokładnie taki sam, ale po ponownym sprawdzeniu widzę, że faktycznie migruje do polecenia drukowania. – mpounsett