Вот что происходит:
- sampleString является байтовой строкой (в кодировке cp1255)
sampleString.decode("cp1255")
декодирует (decode == bytes -> unicode string) строку байта в строку Unicode
print sampleString.decode("cp1255")
пытается вывести строку юникода на стандартный вывод. Для этого при печати необходимо кодировать строку в кодировке Unicode (кодировать == строка в кодировке Unicode -> байты). Ошибка, которую вы видите, означает, что оператор печати python не может записать данную строку юникода в кодировку консоли. sys.stdout.encoding
- кодировка терминала.
Так что проблема в том, что ваша консоль не поддерживает эти символы. Вы должны быть в состоянии настроить консоль, чтобы использовать другую кодировку. Подробная информация о том, как это сделать, зависит от вашей ОС и программы терминала.
Другой подход заключается в ручном указании используемой кодировки:
print sampleString.decode("cp1255").encode("utf-8")
Смотри также:
Простая тестовая программа, с которой вы можете поэкспериментировать:
import sys
print sys.stdout.encoding
samplestring = '\xe0\xe1\xe2\xe3\xe4'
print samplestring.decode("cp1255").encode(sys.argv[1])
На моем терминале utf-8:
$ python2.6 test.py utf-8
UTF-8
אבגדה
$ python2.6 test.py latin1
UTF-8
Traceback (most recent call last):
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-4: ordinal not in range(256)
$ python2.6 test.py ascii
UTF-8
Traceback (most recent call last):
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not in range(128)
$ python2.6 test.py cp424
UTF-8
ABCDE
$ python2.6 test.py iso8859_8
UTF-8
�����
Сообщения об ошибках для latin-1 и ascii означают, что символы Unicode в строке не могут быть представлены в этих кодировках.
Обратите внимание на последние два. Я кодирую строку Unicode в кодировки cp424 и iso8859_8 (две из кодировок, перечисленных в http://docs.python.org/library/codecs.html#standard-encodings, которые поддерживают ивритские символы). Я не получаю исключений при использовании этих кодировок, так как еврейские символы юникода имеют представление в кодировках.
Но мой терминал utf-8 сильно запутывается, когда получает байты в кодировке, отличной от utf-8.
В первом случае (cp424), мой терминал UTF-8 отображает ABCDE, что означает, что представление A utf-8 соответствует представлению cp424 ה, то есть значение 65 байта означает A в utf-8 и ה в cp424.
Метод encode
имеет необязательный строковый аргумент, который можно использовать, чтобы указать, что должно происходить, когда кодировка не может представлять символ ( документация ). Поддерживаемые стратегии являются строгими (по умолчанию), ignore, replace, xmlcharref и backslashreplace. Вы даже можете добавить свои собственные стратегии .
Другая тестовая программа (я печатаю с кавычками вокруг строки, чтобы лучше показать, как игнорирует себя):
import sys
samplestring = '\xe0\xe1\xe2\xe3\xe4'
print "'{0}'".format(samplestring.decode("cp1255").encode(sys.argv[1],
sys.argv[2]))
Результаты:
$ python2.6 test.py latin1 strict
Traceback (most recent call last):
File "test.py", line 4, in <module>
sys.argv[2]))
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-4: ordinal not in range(256)
[/tmp]
$ python2.6 test.py latin1 ignore
''
[/tmp]
$ python2.6 test.py latin1 replace
'?????'
[/tmp]
$ python2.6 test.py latin1 xmlcharrefreplace
'אבגדה'
[/tmp]
$ python2.6 test.py latin1 backslashreplace
'\u05d0\u05d1\u05d2\u05d3\u05d4'