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.

Zestaw
źródło

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)
≥
>>> 
Szalony naukowiec
źródło
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.
70

unicodes potrzebują unicodeciągów formatujących.

>>> print u'{0}'.format(s)
Ignacio Vazquez-Abrams
źródło
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 )

lps
źródło
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