Python: Używanie .format () w łańcuchu znaków ucieczki Unicode


156

Używam Pythona 2.6.5. Mój kod wymaga użycia znaku „więcej niż lub równe”. Oto jest:

>>> s = u'\u2265'
>>> print s
>>> 
>>> print "{0}".format(s)
Traceback (most recent call last):
     File "<input>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2265'
  in position 0: ordinal not in range(128)`  

Dlaczego otrzymuję ten błąd? Czy jest na to właściwy sposób? Muszę użyć tej .format()funkcji.

Odpowiedzi:


243

Po prostu uczyń drugi ciąg również ciągiem znaków Unicode

>>> s = u'\u2265'
>>> print s

>>> print "{0}".format(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2265' in position 0: ordinal not in range(128)
>>> print u"{0}".format(s)
≥
>>> 

40
@Kit: Jeśli chcesz, aby wszystkie literały były w formacie Unicode (jak w Pythonie 3), umieść from __future__ import unicode_literalsna początku plików źródłowych.
Philipp,

1
Tak, dostaniesz to, jeśli jesteś przyzwyczajony do formatowania%, ponieważ ten "% s"% u "\ u2265" działa, ale format "{}". (U "\ u2265") zgłosi wyjątek.
Hylidan

2
co za prosta rzecz ... jaki straszny ból głowy dostałem, dopóki nie znalazłem tego kawałka oświecenia ..
Iosu S.


5

Nieco więcej informacji o tym, dlaczego tak się dzieje.

>>> s = u'\u2265'
>>> print s

działa, ponieważ printautomatycznie używa kodowania systemowego dla twojego środowiska, które prawdopodobnie było ustawione na UTF-8. (Możesz sprawdzić, robiąc import sys; print sys.stdout.encoding)

>>> print "{0}".format(s)

kończy się niepowodzeniem, ponieważ formatpróbuje dopasować kodowanie do typu, do którego jest wywoływany (nie mogłem znaleźć dokumentacji na ten temat, ale zauważyłem to zachowanie). Ponieważ literały łańcuchowe są ciągami bajtów zakodowanymi jako ASCII w Pythonie 2, formatpróbuje zakodować sjako ASCII, co następnie skutkuje tym wyjątkiem. Przestrzegać:

>>> s = u'\u2265'
>>> s.encode('ascii')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2265' in position 0: ordinal not in range(128)

Dlatego w zasadzie działają te podejścia:

>>> s = u'\u2265'
>>> print u'{}'.format(s)

>>> print '{}'.format(s.encode('utf-8'))

Źródłowy zestaw znaków jest zdefiniowany w deklaracji kodowania; jest to ASCII, jeśli w pliku źródłowym nie podano deklaracji kodowania ( https://docs.python.org/2/reference/lexical_analysis.html#string-literals )


1
Aha i stwierdziłem, że jest to bardzo pomocne w zrozumieniu Unicode w Pythonie i ogólnie reprezentacji tekstu w systemach komputerowych: nedbatchelder.com/text/unipain.html
lps
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.