Строковый литерал байта с символами не-ascii

Видимо, я могу сделать это в Python 2.7:

value = '國華' 

Кажется, Python использует кодировку для кодирования символов в строковом литерале в байтовую строку. Что это за кодировка? Это кодировка, определенная в sys.getdefaultencoding() , кодировка исходного файла или что-то еще?

благодаря

getdefaultencoding имеет никакого отношения к кодировке исходного файла или терминала. Это кодировка, используемая для неявного преобразования строк байтов в строки Unicode и всегда должна быть «ascii» на Python 2.X («utf8» на Python 3.X).

На Python 2.X ваша строка кода в скрипте без объявления кодировки вызывает ошибку:

 SyntaxError: Non-ASCII character '\x87' in file ... 

Фактический символ не ASCII может отличаться, но он не будет работать без объявления кодирования. Объявление кодирования требуется для использования символов, отличных от ASCII, на Python 2.X. Объявление кодирования должно соответствовать кодировке исходного файла. Например:

 # coding: utf8 value = '國華' 

при сохранении как cp936 производит:

 SyntaxError: 'utf8' codec can't decode byte 0x87 in position 9: invalid start byte 

Когда кодировка верна, байты в байтовой строке буквально находятся в исходном файле, поэтому они будут содержать закодированные байты символов. Когда Python анализирует строку Unicode, байты декодируются с использованием объявленной исходной кодировки в Unicode. Обратите внимание на разницу при печати строки байта UTF-8 и строки Unicode на консоли cp936:

 # coding: utf8 value = '國華' print value,repr(value) value = u'國華' print value,repr(value) 

Вывод:

 鍦嬭彲 '\xe5\x9c\x8b\xe8\x8f\xaf'國華 u'\u570b\u83ef' 

Строка байтов содержит 3-байтные кодировки UTF-8 двух символов, но отображается неправильно, поскольку последовательность байтов не понятна терминалу cp936. Юникод напечатан правильно, а строка содержит кодовые точки Юникода, декодированные из байтов UTF-8 исходного файла.

Обратите внимание на разницу при объявлении и использовании кодировки, которая соответствует терминалу:

 # coding: cp936 value = '國華' print value,repr(value) value = u'國華' print value,repr(value) 

Вывод:

 國華 '\x87\xf8\xc8A'國華 u'\u570b\u83ef' 

Содержимое строки байта теперь представляет собой 2-байтные кодировки cp936 двух символов («A», эквивалентные «\ x41») и отображается правильно, так как терминал понимает последовательность байтов cp936. Строка Unicode содержит те же кодовые точки Юникода для двух символов, что и предыдущий пример, потому что последовательность исходного байта была декодирована с использованием объявленной исходной кодировки в Unicode.

Если сценарий имеет правильное объявление кодировки источника и использует строки Unicode для текста, он отображает правильные символы 1 независимо от терминальной кодировки 2 . Он будет UnicodeEncodeError если терминал не поддерживает символ, а не отображает неправильный символ.

Заключительное примечание: Python 2.X по умолчанию использует кодировку ascii, если не объявлено иначе, и разрешает символы без символов ASCII в байтовых строках, если их поддерживает кодировка. Python 3.X по умолчанию использует «utf8» кодировку (поэтому не забудьте сохранить в этой кодировке или объявить иначе) и не допускает символов, отличных от ASCII, в байтовых строках.

1 Если шрифт терминала поддерживает символ.
2 Если кодировка терминала поддерживает символ.

 value = b'國華' 

не имеет смысла ( b подразумевается в Python 2.x) – зачем вы хотите, чтобы строка байтов содержала символы ? Python просто воспроизводит байты в любой кодировке, используемой вашим терминалом / редактором. То, что вы хотите, это строка символов :

 value = u'國華' 

В исходном коде файла (в отличие от интерактивной оболочки) не забудьте объявить кодировку , добавив следующую строку в начало файла:

 # -*- coding: utf-8 -*-