Python to unicode string: Unicode HOWTO — Python 3.8.6 documentation
python unicode — приведение к строке, методы encode/decode
Значения объектов типа «string» по умолчанию задается в Python unicode. Приведение к строке требуется обычно для объектов типа bytes. Они получаются при обработке вывода, например, subprocess.
Юникод нужен при работе с символами нескольких языков. Кириллица, буквы греческого алфавита, иероглифы и т.п. не будут передаваться при вводе их через формы обратной связи. Выполнение скрипта будет завершаться ошибкой если не использовать юникод:
[Sat Aug 25 04:40:52.573105 2018] [cgid:error] [pid 28564:tid 139992957437696] [client 212.104.87.172:40958] End of script output before headers: add.cgi, referer: http://example.com/page.html
Traceback (most recent call last):
File «/var/www/site/restore.cgi», line 44, in <module>
print («<h3>\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0436\u0438\u0434\u0430\u0439\u0442\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 </h3>»)
UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 4-12: ordinal not in range(128)
Из сообщения об ошибке следует, что кодек ascii не может обрабатывать символы в кодировке, отличной от ASCII. Чтобы работать с этими символами требуется UTF-8.
В юникоде символы кодируются и приводятся к виду \uXXXX. Затем обрабатываются скриптом, далее можно выполнить обратное преобразование.
Можно использовать два метода (переменная text содержит объект bytes с юникодом):
1)
text.decode(‘utf-8’)
2)
str(text, ‘utf-8’)
Приведение к строке
Определяем переменную
>> text = «русский текст»
Переводим значение в юникод
>> text. encode(‘utf-8’)
b’\xd1\x80\xd1\x83\xd1\x81\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9 \xd1\x82\xd0\xb5\xd0\xba\xd1\x81\xd1\x82′
>> encoded = text.encode(‘utf-8’)
Тип объекта должен быть bytes
> print (type(encoded))
<class ‘bytes’>
Теперь текст можно расшифровать
>> print (encoded.decode(‘utf-8’))
русский текст
Функции Python encode() и decode()
Методы encode
и decode
Python используются для кодирования и декодирования входной строки с использованием заданной кодировки. Давайте подробно рассмотрим эти две функции.
encode заданной строки
Мы используем метод encode()
для входной строки, который есть у каждого строкового объекта.
Формат:
input_string.encode(encoding, errors)
Это кодирует input_string
с использованием encoding
, где errors
определяют поведение, которому надо следовать, если по какой-либо случайности кодирование строки не выполняется.
encode()
приведет к последовательности bytes
.
inp_string = 'Hello' bytes_encoded = inp_string.encode() print(type(bytes_encoded))
Как и ожидалось, в результате получается объект <class 'bytes'>
:
<class 'bytes'>
Тип кодирования, которому надо следовать, отображается параметром encoding
. Существуют различные типы схем кодирования символов, из которых в Python по умолчанию используется схема UTF-8.
Рассмотрим параметр encoding
на примере.
a = 'This is a simple sentence. ' print('Original string:', a) # Decodes to utf-8 by default a_utf = a.encode() print('Encoded string:', a_utf)
Вывод
Original string: This is a simple sentence. Encoded string: b'This is a simple sentence.'
Как вы можете заметить, мы закодировали входную строку в формате UTF-8. Хотя особой разницы нет, вы можете заметить, что строка имеет префикс b
. Это означает, что строка преобразуется в поток байтов.
На самом деле это представляется только как исходная строка для удобства чтения с префиксом b
, чтобы обозначить, что это не строка, а последовательность байтов.
Обработка ошибок
Существуют различные типы errors
, некоторые из которых указаны ниже:
Тип ошибки | Поведение |
strict | Поведение по умолчанию, которое вызывает UnicodeDecodeError при сбое. |
ignore | Игнорирует некодируемый Unicode из результата. |
replace | Заменяет все некодируемые символы Юникода вопросительным знаком (?) |
backslashreplace | Вставляет escape-последовательность обратной косой черты (\ uNNNN) вместо некодируемых символов Юникода. |
Давайте посмотрим на приведенные выше концепции на простом примере. Мы рассмотрим входную строку, в которой не все символы кодируются (например, ö
),
a = 'This is a bit möre cömplex sentence.' print('Original string:', a) print('Encoding with errors=ignore:', a.encode(encoding='ascii', errors='ignore')) print('Encoding with errors=replace:', a.encode(encoding='ascii', errors='replace'))
Вывод
Original string: This is a möre cömplex sentence. Encoding with errors=ignore: b'This is a bit mre cmplex sentence.' Encoding with errors=replace: b'This is a bit m?re c?mplex sentence. '
Декодирование потока байтов
Подобно кодированию строки, мы можем декодировать поток байтов в строковый объект, используя функцию decode()
.
Формат:
encoded = input_string.encode() # Using decode() decoded = encoded.decode(decoding, errors)
Поскольку encode()
преобразует строку в байты, decode()
просто делает обратное.
byte_seq = b'Hello' decoded_string = byte_seq.decode() print(type(decoded_string)) print(decoded_string)
Вывод
<class 'str'> Hello
Это показывает, что decode()
преобразует байты в строку Python.
Подобно параметрам encode()
, параметр decoding
определяет тип кодирования, из которого декодируется последовательность байтов. Параметр errors
обозначает поведение в случае сбоя декодирования, который имеет те же значения, что и у encode()
.
Важность кодировки
Поскольку кодирование и декодирование входной строки зависит от формата, мы должны быть осторожны при этих операциях. Если мы используем неправильный формат, это приведет к неправильному выводу и может вызвать ошибки.
Первое декодирование неверно, так как оно пытается декодировать входную строку, которая закодирована в формате UTF-8. Второй правильный, поскольку форматы кодирования и декодирования совпадают.
a = 'This is a bit möre cömplex sentence.' print('Original string:', a) # Encoding in UTF-8 encoded_bytes = a.encode('utf-8', 'replace') # Trying to decode via ASCII, which is incorrect decoded_incorrect = encoded_bytes.decode('ascii', 'replace') decoded_correct = encoded_bytes.decode('utf-8', 'replace') print('Incorrectly Decoded string:', decoded_incorrect) print('Correctly Decoded string:', decoded_correct)
Вывод
Original string: This is a bit möre cömplex sentence. Incorrectly Decoded string: This is a bit m��re c��mplex sentence. Correctly Decoded string: This is a bit möre cömplex sentence.
Строки символов Unicode в Python 2 и Python 3
Винсент: Знаешь, что самое забавное в Европе?
Джулс: Что?
Винсент: Такие маленькие отличия. Там вроде все то же самое, что и
здесь, но чуть-чуть отличается.«Криминальное чтиво»
Как известно, ключевым отличием Python 3.x от Python 2.x является переориентация языка и стандартных библиотек со строк байтов на строки символов Unicode. Когда я решил повнимательнее посмотреть на это различие, пришлось копнуть вглубь и вширь, а результаты моих раскопок я оформил в статью, которую предлагаю вашему вниманию.
В Python 2 | В Python 3 |
---|---|
строковый литерал получает тип str | строковый литерал получает тип str |
тип str представляет собой строку байтов | тип str представляет собой строку символов Unicode |
для представления строки символов Unicode используется тип unicode | для представления строки байтов используется тип bytes |
для представления строки unicode в нужной кодировке используется метод unicode. encode(кодировка) , возвращающий строку байтов str | для представления строки str в нужной кодировке используется метод str.encode(кодировка) , возвращающий строку байтов bytes |
для преобразования строки байтов str в строку unicode используется метод str.decode(кодировка) , возвращающий строку unicode | для преобразования строки байтов bytes в строку str используется метод bytes.decode(кодировка) , возвращающий строку str |
системная кодировка по умолчанию, она же кодировка исходных файлов по умолчанию, ASCII | системная кодировка по умолчанию, она же кодировка исходных файлов по умолчанию, UTF-8 |
при записи в файл строки по умолчанию преобразуются в системную кодировку по умолчанию | при записи в файл строки по умолчанию преобразуются в кодировку, определяемую пользовательскими настройками |
идентификаторы в программе содержат только символы ASCII, не могут использовать никаких других букв, кроме латинских | идентификаторы в программе содержат символы Unicode, могут использовать буквы других алфавитов, кроме латинского |
Мои эксперименты я ставлю под ОС Windows 7 в стандартной консоли.
Для разминки, несколько манипуляций со строковыми литералами и переменными в Python 2:
>>> s = 'Hello'
>>> s
'Hello'
>>> type(s)
<type 'str'>
>>> u = s.decode('ascii')
>>> u
u'Hello'
>>> type(u)
<type 'unicode'>
И в Python 3:
>>> s = 'Hello'
>>> s
'Hello'
>>> type(s)
<class 'str'>
>>> b = s.encode('ascii')
>>> b
b'Hello'
>>> type(b)
<class 'bytes'>
Теперь посмотрим на кодировки, используемые в Python 2 и Python 3 по умолчанию:
- Системная кодировка по умолчанию (system default encoding), возвращается функцией
sys.getdefaultencoding()
. Это кодировка исходных текстов Python по умолчанию, она же используется по умолчанию для кодирования и декодирования строкunicode
. - Кодировки стандартных потоков ввода, вывода и ошибок — файловых объектов, атрибуты
sys. stdin.encoding
,sys.stdout.encoding
иsys.stderr.encoding
, соответственно. Строки символов Unicode, посылаемые в канал вывода, преобразуются в соответствующую кодировку (или в системную кодировку по умолчанию, если атрибутencoding is None
). - Кодировка имен файлов в файловой системе, возвращается функцией
sys.getfilesystemencoding()
. Имена файлов, представленные в программе на Python как строки символов Unicode, преобразуются в эту кодировку для взаимодействия с файловой системой (или в системную кодировку по умолчанию, еслиsys.getfilesystemencoding()
возвращаетNone
). - Кодировка для текстовых данных, заданная пользовательскими настройками, возвращается функцией
locale.getpreferredencoding(False)
.
Кодировки в Python 2:
>>> import sys, locale
>>> sys.getdefaultencoding()
'ascii'
>>> sys.stdin.encoding
'cp866'
>>> sys. stdout.encoding
'cp866'
>>> sys.stderr.encoding
'cp866'
>>> sys.getfilesystemencoding()
'mbcs'
>>> locale.getpreferredencoding(False)
'cp1251'
Кодировки в Python 3:
>>> import sys, locale
>>> sys.getdefaultencoding()
'utf-8'
>>> sys.stdin.encoding
'cp866'
>>> sys.stdout.encoding
'cp866'
>>> sys.stderr.encoding
'cp866'
>>> sys.getfilesystemencoding()
'mbcs'
>>> locale.getpreferredencoding(False)
'cp1251'
Как видим, системной кодировкой по умолчанию для Python 2 является ascii
, а для Python 3 — utf-8
. И это единственное обнаруженное различие.
Нам, русским, очень «повезло» с обилием кириллических кодировок в Windows. Работая в консоли Windows, по умолчанию мы имеем дело с кириллической кодировкой cp866
. Работая с текстовым файлом в Блокноте, по умолчанию мы работаем в кириллической кодировке cp1251
. Имена файлов, использующие русские символы, в файловой системе Windows представлены в кодировке mbcs
(multi-byte character set), — это двухбайтовая кодировка, которая позволяет представить подмножество символов Unicode (UTF-16?).
Вооружившись знанием об используемых по умолчанию кодировках, попробуем в интерактивном режиме Pyhton вводить и выводить строки, включающие нелатинские символы.
Фрагмент интерактивного сеанса Python 2:
>>> u = u'Привет world'
>>> type(u)
<type 'unicode'>
>>> u
u'\u041f\u0440\u0438\u0432\u0435\u0442 world'
>>> print u, u.encode('cp866')
Привет world Привет world
Что я только что сделал?
Команды вводятся через стандартный входной поток, использующий кодировку cp866
(sys.stdin.encoding
). Таким образом, в первом предложении присваивания литерал u'Привет world'
преобразуется в строку unicode
из кодировки cp866
и полученная строка unicode
присваивается переменной u
. Далее я проверил тип и значение переменной u
и увидел, что русские буквы представлены двухбайтовыми кодами Unicode. Наконец, предложение print
посылает в стандартный выходной поток данную строку unicode
и строку str
, полученную преобразованием строки u
в кодировку cp866
. Результат вывода обеих строк одинаков, поскольку строка unicode
неявно преобразуется при выводе в стандартый выходной поток в кодировку cp866
(sys.stdout.encoding
).
В Python 3 получим такой результат (предлагаю интерпретировать его самостоятельно):
>>> s = 'Привет world'
>>> type(s)
<class 'str'>
>>> s
'Привет world'
>>> print(s, s.encode('cp866'))
Привет world b'\x8f\xe0\xa8\xa2\xa5\xe2 world'
Идем дальше.
В Python 2 для использования в скриптах не-ASCII символов нужно явно указывать кодировку исходного файла, поскольку системная кодировка по умолчанию, ascii
, подразумевает использование в файле только символов ASCII. А в Python 3 исходный файл по умолчанию содержит символы Unicode в кодировке utf-8
, что позволяет использовать в нем практически любые символы без явного указания кодировки.
Файл hello.py в кодировке UTF-8 для Python 2:
# -*- coding: utf-8 -*-
s = u'Привет world!'
print type(s), s, s.encode('cp866')
Выполню его в консоли Windows:
C:\_sandbox> c:\Python27\python.exe hello.py
<type 'unicode'> Привет world! Привет world!
Файл hello3.py в кодировке UTF-8 для Python 3:
# нас устраивает кодировка по умолчанию utf-8
s = 'Привет world!'
print(type(s), s, s.encode('cp866'))
Выполню его в консоли Windows:
C:\_sandbox> c:\Python33\python.exe hello3.py
<class 'str'> Привет world! b'\x8f\xe0\xa8\xa2\xa5\xe2 world!'
Разница с работой скрипта hello.py
в том, что теперь к кодировке стандартного потока вывода приводится значение типа str
, и строка байтов bytes
не интерпретируется как строка читабельных символов.
Следующий скрипт helloname.py
демонстрирует ввод и вывод кириллических символов в Python 2, используя для их хранения строки unicode
:
# -*- coding: utf-8 -*-
import sys
def uraw_input(prompt):
return unicode(raw_input(prompt.encode(sys.stdout.encoding)), sys.stdin.encoding)
name = uraw_input(u'Привет! Ваше имя? ')
print u'Привет, %s!' % name
Выполню скрипт в консоли Windows:
C:\_dev\GOLD>c:\Python27\python.exe helloname.py
Привет! Ваше имя? Андрей
Привет, Андрей!
Посмотрим теперь, что происходит при записи строк символов Unicode в файл. Если в Python 2 явно не преобразовывать выводимые в файл строки unicode
в строки str
с нужной кодировкой, то получим ошибку.
# -*- coding: UTF-8 -*-
with open('hello.txt', 'w') as f:
print 'File encoding:', f.encoding
f.write(u'Привет world!')
Выполню скрипт в консоли Windows:
C:\_sandbox> c:\Python27\python. exe hellofile.py
File encoding: None
Traceback (most recent call last):
File "hellofile.py", line 5, in
f.write(u'╨Я╤А╨╕╨▓╨╡╤В world!')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
При записи в файл Python 2 пытается преобразовать строку unicode
в системную кодировку по умолчанию, ascii
, поскольку атрибут encoding
открытого нами файла имеет значение None
. В кодировке ascii
нельзя представить кириллические символы, из-за чего и возникает ошибка.
Во избежание ошибок, при записи строк unicode
в файл нужно явно приводить их к желаемой кодировке:
# -*- coding: UTF-8 -*-
with open('hello.txt', 'w') as f:
print 'File encoding:', f.encoding
f.write(u'Привет world!'.encode('cp866'))
Выполню исправленный скрипт в консоли Windows:
C:\_sandbox> c:\Python27\python.exe hellofile. py
File encoding: None
C:\_sandbox> type hello.txt
Привет world!
Аналогичный эксперимент с Python 3 показывает, что строки пишутся в файл в кодировке, определяемой локалью пользователя!
with open('hello3.txt', 'w') as f:
print('File encoding:', f.encoding)
f.write('Привет world!')
Выполняю скрипт в консоли Windows:
C:\_sandbox> c:\Python33\python.exe hellofile3.py
File encoding: cp1251
Выше мы видели, что на русифицированной Windows функция locale.getpreferredencoding(False)
возвращает 'cp1251'
. Именно с этой кодировкой открывается новый файл по умолчанию, и, как следствие, к ней приводятся строки, записываемые в этот файл.
С кодировкой файла cp1251
запись в него смешанной латино-кириллической строки проходит на ура, а вот попытка записи кандзи вместе с кириллицей приводит к уже знакомой нам ошибке:
with open('hello31. txt', 'w') as f:
print('File encoding:', f.encoding)
f.write('Привет 世界!')
Выполняю скрипт в консоли Windows:
C:\_sandbox> c:\Python33\python.exe hellofile31.py
File encoding: cp1251
Traceback (most recent call last):
File "hellofile31.py", line 3, in
f.write('Привет \u4e16\u754c!')
File "c:\Python33\lib\encodings\cp1251.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 7-8: character maps to
Кодировка cp1251
не кодирует кандзи!
Хорошая новость в том, что в Python 3, в отличие от Python 2, при открытии файла можно явно указать кодировку файла. В эту кодировку и будут преобразовываться строки str
при записи в файл; из этой кодировки будут преобразовываться в str
читаемые из файла строки байтов.
Укажу явно кодировку открываемых файлов в скрипте hello32. py
:
with open('hello31.txt', 'w', encoding='utf-8') as f:
print('File encoding:', f.encoding)
f.write('Привет world!')
with open('hello32.txt', 'w', encoding='utf-8') as f:
print('File encoding:', f.encoding)
f.write('Привет 世界!')
with open('hello31.txt', encoding='utf-8') as f:
print('File encoding:', f.encoding)
print(f.read())
Выполняю скрипт в консоли Windows:
C:\_sandbox> c:\Python33\python.exe hellofile32.py
File encoding: utf-8
File encoding: utf-8
File encoding: utf-8
Привет world!
Как видим, скрипт пишет в файл и читает из файла строки в кодировке utf-8
.
В заключение, экзотический пример кода. Вследствие того, что в Python 3 системной кодировкой по умолчанию является utf-8
, в Python 3 можно использовать в идентификаторах не только латиницу, но и другие символы Unicode:
>>> def привет_5_раз(имя):
... for i in range(5):
. .. print('Привет,', имя)
...
>>> привет_5_раз('Медвет')
Привет, Медвет
Привет, Медвет
Привет, Медвет
Привет, Медвет
Привет, Медвет
Сопровождать такой код и вносить в него изменения интернациональной команде разработчиков будет проблематично!
Проделанные сравнительные эксперименты не дали мне достаточно оснований, чтобы решительно встать на одну из сторон в священной войне между защитниками Python 2 и энтузиастами Python 3 :). Хотя Unicode-ориентированность Python 3 и то, как это сказывается на прикладном программировании, мне нравится.
Как преобразовать строку в utf-8 в Python
У меня есть браузер, который отправляет символы utf-8 на мой сервер Python, но когда я получаю его из строки запроса, кодировка, которую возвращает Python, — ASCII. Как преобразовать обычную строку в utf-8?
Примечание: строка, переданная из интернета, уже кодируется UTF-8, я просто хочу, чтобы Python рассматривал ее как UTF-8, а не ASCII. преобразование в unicode и указание кодировки.
219
автор: user225312
Если методы выше не работают, вы также можете сказать Python игнорировать части строки, которые он не может преобразовать в utf-8:
stringnamehere.decode('utf-8', 'ignore')
может быть немного перебор, но когда я работаю с ascii и unicode в тех же файлах, повторное декодирование может быть болью, вот что я использую:
def make_unicode(input):
if type(input) != unicode:
input = input. decode('utf-8')
return input
else:
return input
16
автор: Blueswannabe
Если я правильно вас понимаю, у вас есть кодированная байтовая строка utf-8 в вашем коде.
преобразование байтовой строки в строку unicode называется декодированием (unicode -> byte-string-кодирование).
Вы делаете это с помощью unicode или расшифруйте метод. Либо:
unicodestr = unicode(bytestr, encoding)
unicodestr = unicode(bytestr, "utf-8")
или:
unicodestr = bytestr.decode(encoding)
unicodestr = bytestr.decode("utf-8")
добавление следующей строки в верхнюю часть вашего . файл py:
# -*- coding: utf-8 -*-
позволяет кодировать строки непосредственно в вашем скрипте, например:
utfstr = "ボールト"
city = 'Ribeir\xc3\xa3o Preto'
print city.decode('cp1252').encode('utf-8')
в Python 3.6 у них нет встроенной функции unicode ().
Чтобы преобразовать строку в unicode, просто получите значение unicode символа и сделайте следующее:
my_str = "\u221a25"
my_str = u"{}".format(my_str)
print(my_str)
>>> √25
6
автор: Zld Productions
перевести с помощью ord () и unichar ().
Каждый символ unicode имеет число, связанное, что-то вроде индекса. Таким образом, у Python есть несколько методов для перевода между char и его номером. Недостаток-это пример. Надеюсь, это поможет.
>>> C = 'ñ'
>>> U = C.decode('utf8')
>>> U
u'\xf1'
>>> ord(U)
241
>>> unichr(241)
u'\xf1'
>>> print unichr(241).encode('utf8')
ñ
Python Language — Полезные константы модуля String
пример
string
модуль Python предоставляет константы для операций, связанных с строкой. Чтобы использовать их, импортируйте string
модуль:
>>> import string
string.ascii_letters
:
Конкатенация ascii_lowercase
и ascii_uppercase
:
>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
string. ascii_lowercase
:
Содержит все символы ASCII нижнего регистра:
>>> string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'
string.ascii_uppercase
:
Содержит все символы ASCII верхнего регистра:
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
string.digits
:
Содержит все десятичные знаковые символы:
>>> string.digits
'0123456789'
string.hexdigits
:
Содержит все символы шестнадцатеричной цифры:
>>> string.hexdigits
'0123456789abcdefABCDEF'
string.octaldigits
:
Содержит все восьмеричные цифры:
>>> string.octaldigits
'01234567'
string.punctuation
:
Содержит все символы, которые считаются пунктуацией в локали C
:
>>> string. _`{|}~ \t\n\r\x0b\x0c'
Pragmatic Unicode
Pragmatic Unicode
Ned Batchelder @nedbat
bit.ly/unipain
Hi, I’m Ned Batchelder. I’ve been writing in Python for over ten years,
which means at least a half-dozen times, I’ve made the same Unicode
mistakes that everyone else has.
Wrote a nice program
It worked!
Accented chars
UnicodeError!
😁
👽
💥
😞
If you’re like most Python programmers, you’ve done it too: you’ve built
a nice application, and everything seemed to be going fine. Then one day
an accented character appeared out of nowhere, and your program started
belching UnicodeErrors.
You kind of knew what to do with those, so you added an encode or a
decode where the error was raised, but the UnicodeError happened somewhere
else. You went to the new place, and added a decode, maybe an encode.
After playing whack-a-mole like this for a while, the problem seemed to be
fixed.
Then a few days later, another accent appeared in another place, and you
had to play a little bit more whack-a-mole until the problem finally
stopped.
Annoyed
Angry
Uninterested
😠
😕
So now you have a program that works, but you’re annoyed and
uncomfortable, it took too long, you know it isn’t «right,» and you hate
yourself. And the main thing you know about Unicode is that you don’t like
Unicode.
You don’t want to know about weirdo character sets, you just want
to be able to write a program that doesn’t make you feel bad.
5 Facts of Life
3 Pro Tips
You don’t have to play whack-a-mole. Unicode isn’t simple, but it isn’t
difficult either. With knowledge and discipline, you can deal with Unicode
easily and with grace.
I’ll teach you five Facts of Life, and give you three Pro Tips that will
solve your Unicode problems. We’re going to cover the basics of Unicode,
and how both Python 2 and Python 3 work. They are different, but the
strategies you’ll use are basically the same.
We’ll start with the basics of Unicode.
Fact of Life #1
Computers are built on bytes
Files + Networks
Everything
The first Fact of Life: everything in a computer is bytes. Files on
disk are a series of bytes, and network connections only transmit bytes.
Almost without exception, all the data going into or out of any program you
write, is bytes.
The problem with bytes is that by themselves they are meaningless, we
need conventions to give them meaning.
To represent text, we’ve been using the ASCII code for nearly 50 years.
Every byte is assigned one of 95 symbols. When I send you a byte 65, you
know that I mean an upper-case A, but only because we’ve agreed beforehand
on what each byte represents.
ISO Latin 1, or 8859-1, is ASCII extended with 96 more symbols.
Windows added 27 more symbols to produce CP1252. This is pretty much
the best you can do to represent text as single bytes, because there’s not
much room left to add more symbols.
Fact of Life #2
The world needs more than 256 symbols
Hello, world! • Здравствуй, мир!
Ողջո՜ւյն աշխարհ • !مرحبا ، العالم
!שלום, עולם • 여보세요 세계!
नमस्ते, दुनिया! • 你好,世界!
With character sets like these, we can represent at most 256 characters.
But Fact of Life #2 is that there are way more than 256 symbols in the
world’s text. A single byte simply can’t represent text world-wide.
During your darkest whack-a-mole moments, you may have wished that everyone
spoke English, but it simply isn’t so. People need lots of symbols to
communicate.
Fact of Life #1 and Fact of Life #2 together create a fundamental
conflict between the structure of our computing devices, and the needs of
the world’s people.
Map single bytes to characters
Pretend FoL#2 doesn’t exist
8859-1 through -16
cp850, cp1252, etc
EBCDIC, APL, BBQ, OMG, WTF
Chaos!
There have been a number of attempts to resolve this conflict.
Single-byte character codes like ASCII map bytes to characters.
Each one pretends that Fact of Life #2 doesn’t exist.
There are many single-byte codes, and they don’t solve the problem.
Each is only good for representing one small slice of human language. They
can’t solve the global text problem.
Map two bytes to characters
Shift-JIS, GB2312, Big5, etc.
Still no agreement
People tried creating double-byte character sets, but they were still
fragmented, serving different subsets of people. There were multiple
standards in place, and they still weren’t large enough to deal
with all the symbols needed.
Assigns characters to code points (integers)
1.1M code points
110K assigned
A-Z …
☃ …
Жณ賃 …
💩 …
Unicode was designed to deal decisively with the issues with
older character codes. Unicode assigns integers, known as code points, to
characters. It has room for 1.1 million code points, and only 110,000 are
already assigned, so there’s plenty of room for future growth.
Unicode’s goal is to have everything. It starts with ASCII, and
includes thousands of symbols, including the famous Snowman, covers all the
writing systems of the world, and is constantly being expanded. For
example, the latest update gave us the symbol PILE OF POO.
U+2119: DOUBLE-STRUCK CAPITAL P
U+01B4: LATIN SMALL LETTER Y WITH HOOK
U+2602: UMBRELLA
U+210C: BLACK-LETTER CAPITAL H
U+00F8: LATIN SMALL LETTER O WITH STROKE
U+1F24: GREEK SMALL LETTER ETA WITH PSILI AND OXIA
Here is a string of six exotic Unicode characters. Unicode code points
are written as 4-, 5-, or 6-digits of hex with a U+ prefix. Every
character has an unambiguous full name which is always in uppercase ASCII.
This string is designed to look like the word «Python», but doesn’t use
any ASCII characters at all.
Have to map Unicode code points to bytes somehow
UTF-16, UTF-32, UCS-2, UCS-4, UTF-8
So Unicode makes room for all of the characters we could ever need,
but we still have Fact of Life #1 to deal with: computers need bytes.
We need a way to represent Unicode code points as bytes in order to
store or transmit them.
The Unicode standard defines a number of ways to represent code points
as bytes. These are called encodings.
The king of encodings
Variable length
ASCII characters are still one byte
48 | 69 | e2 | 84 | 99 | c6 | b4 | e2 | 98 | 82 | e2 | 84 | 8c | c3 | b8 | e1 | bc | a4 |
H | i | ℙ | ƴ | ☂ | ℌ | ø | ἤ |
UTF-8 is easily the most popular encoding for storage and transmission
of Unicode. It uses a variable number of bytes for each code point. The
higher the code point value, the more bytes it needs in UTF-8. ASCII
characters are one byte each, using the same values as ASCII, so ASCII is a
subset of UTF-8.
Here we show our exotic string as UTF-8. The ASCII characters H and i are
single bytes, and other characters use two or three bytes depending on their
code point value. Some Unicode code points require four bytes, but we aren’t
using any of those here.
OK, enough theory, let’s talk about Python 2. In the slides, Python 2
samples have a big 2 in the upper-right corner, Python 3 samples will have
a big 3.
str: a sequence of bytes
unicode: a sequence of code points (unicode)
2
>>> my_string = "Hello World" >>> type(my_string) <type 'str'> >>> my_unicode = u"Hi \u2119\u01b4\u2602\u210c\xf8\u1f24" >>> type(my_unicode) <type 'unicode'>
In Python 2, there are two different string data types. A plain-old
string literal gives you a «str» object, which stores bytes. If you use a
«u» prefix, you get a «unicode» object, which stores code points. In a
unicode string literal, you can use backslash-u to insert any Unicode code
point.
Notice that the word «string» is problematic. Both «str» and «unicode»
are kinds of strings, and it’s tempting to call either or both of them
«string,» but it’s better to use more specific terms to keep things
straight.
unicode .encode() → bytes
bytes .decode() → unicode
2
>>> my_unicode = u"Hi \u2119\u01b4\u2602\u210c\xf8\u1f24" >>> len(my_unicode) 9 >>> my_utf8 = my_unicode.encode('utf-8') >>> len(my_utf8) 19 >>> my_utf8 'Hi \xe2\x84\x99\xc6\xb4\xe2\x98\x82\xe2\x84\x8c\xc3\xb8\xe1\xbc\xa4' >>> my_utf8. decode('utf-8') u'Hi \u2119\u01b4\u2602\u210c\xf8\u1f24'
Byte strings and unicode strings each have a method to convert it to
the other type of string. Unicode
strings have a .encode() method that produces bytes, and byte strings have
a .decode() method that produces unicode. Each takes an argument, which
is the name of the encoding to use for the operation.
We can define a Unicode string named my_unicode, and see that it has
9 characters. We can encode it to UTF-8 to create the my_utf8 byte string,
which has 19 bytes. As you’d expect, reversing the operation by decoding
the UTF-8 string produces the original Unicode string.
Many encodings only do a subset of Unicode
2
>>> my_unicode.encode('ascii') Traceback (most recent call last): UnicodeEncodeError: 'ascii' codec can't encode characters in position 3-8: ordinal not in range(128)
Unfortunately, encoding and decoding can produce errors if the data
isn’t appropriate for the specified encoding. Here we try to encode our
exotic Unicode string to ASCII. It fails because ASCII can only represent
charaters in the range 0 to 127, and our Unicode string has code points
outside that range.
The UnicodeEncodeError that’s raised indicates the encoding being used,
in the form of the «codec» (short for coder/decoder), and the actual
position of the character that caused the problem.
Not all byte sequences are valid
2
>>> my_utf8.decode("ascii") Traceback (most recent call last): UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 3: ordinal not in range(128) >>> "\x78\x9a\xbc\xde\xf0".decode("utf-8") Traceback (most recent call last): return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode byte 0x9a in position 1: invalid start byte
Decoding can also produce errors. Here we try to decode our UTF-8
string as ASCII and get a UnicodeDecodeError because again, ASCII can only
accept values up to 127, and our UTF-8 string has bytes outside that
range.
Even UTF-8 can’t decode any sequence of bytes. Next we try to decode
some random junk, and it also produces a UnicodeDecodeError. Actually,
one of UTF-8’s advantages is that there are invalid sequences of bytes,
which helps to build robust systems: mistakes in data won’t be accepted as
if they were valid.
2
>>> my_unicode.encode("ascii", "replace") 'Hi ??????' >>> my_unicode.encode("ascii", "xmlcharrefreplace") 'Hi ℙƴ☂ℌøἤ' >>> my_unicode.encode("ascii", "ignore") 'Hi '
When encoding or decoding, you can specify what should happen when
the codec can’t handle the data. An optional second argument to encode or
decode specifies the policy. The default value is «strict», which means
raise an error, as we’ve seen.
A value of «replace» means, give me a standard replacement character.
When encoding, the replacement character is a question mark, so any code
point that can’t be encoded using the specified encoding will simply
produce a «?».
Other error handlers are more useful. «xmlcharrefreplace» produces
an HTML/XML character entity reference, so that \u01B4 becomes «ƴ»
(hex 01B4 is decimal 436.) This is very useful if you need to output
unicode for an HTML file.
Notice that different error policies are used for different reasons.
«Replace» is a defensive mechanism against data that cannot be interpreted,
and loses information. «Xmlcharrefreplace» preserves all the original
information, and is used when outputting data where XML escapes are
acceptable.
2
>>> my_utf8.decode("ascii", "ignore") u'Hi ' >>> my_utf8.decode("ascii", "replace") u'Hi \ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd'
Hi ����������������
You can also specify error handling when decoding. «Ignore» will drop
bytes that can’t decode properly. «Replace» will insert a Unicode U+FFFD,
«REPLACEMENT CHARACTER» for problem bytes. Notice that since the decoder
can’t decode the data, it doesn’t know how many Unicode characters were
intended. Decoding our UTF-8 bytes as ASCII produces 16 replacement
characters, one for each byte that couldn’t be decoded, while those bytes
were meant to only produce 6 Unicode characters.
Mixing bytes and unicode implicitly decodes
2
>>> u"Hello " + "world" u'Hello world' >>> u"Hello " + ("world". decode("ascii")) u'Hello world' >>> sys.getdefaultencoding() 'ascii'
Python 2 tries to be helpful when working with unicode and byte strings.
If you try to perform a string operation that combines a unicode string
with a byte string, Python 2 will automatically decode the byte string to
produce a second unicode string, then will complete the operation with the
two unicode strings.
For example, we try to concatenate a unicode «Hello » with a byte string
«world». The result is a unicode «Hello world». On our behalf, Python 2
is decoding the byte string «world» using the ASCII codec. The encoding
used for these implicit decodings is the value of
sys.getdefaultencoding().
The implicit encoding is ASCII because it’s the only safe guess: ASCII
is so widely accepted, and is a subset of so many encodings, that it’s
unlikely to produce false positives.
2
>>> u"Hello " + my_utf8 Traceback (most recent call last): UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 3: ordinal not in range(128) >>> u"Hello " + (my_utf8.decode("ascii")) Traceback (most recent call last): UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 3: ordinal not in range(128)
Of course, these implicit decodings are not immune to decoding errors. If you
try to combine a byte string with a unicode string and the byte string can’t be
decoded as ASCII, then the operation will raise a UnicodeDecodeError.
This is the source of those painful UnicodeErrors. Your code
inadvertently mixes unicode strings and byte strings, and as long as the
data is all ASCII, the implicit conversions silently succeed. Once a
non-ASCII character finds its way into your program, an implicit decode
will fail, causing a UnicodeDecodeError.
Converting implicitly: helpful?
Works great when everything is ASCII
When that fails: PAIN
Python 2’s philosophy was that unicode strings and byte strings are
confusing, and it tried to ease your burden by automatically converting
between them, just as it does for ints and floats. But the conversion
from int to float can’t fail, while byte string to unicode string can.
Python 2 silently glosses over byte to unicode conversions, making it
much easier to write code that deals with ASCII. The price you pay is
that it will fail with non-ASCII data.
2
>>> "Title: %s" % my_unicode u'Title: Hi \u2119\u01b4\u2602\u210c\xf8\u1f24' >>> u"Title: %s" % my_string u'Title: Hello World' >>> print my_unicode Traceback (most recent call last): UnicodeEncodeError: 'ascii' codec can't encode characters in position 3-8: ordinal not in range(128) >>> my_utf8. encode('utf-8') # silly Traceback (most recent call last): UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 3: ordinal not in range(128) >>> my_string.encode('utf-8') # silly 'Hello World'
There are lots of ways to combine two strings, and all of them will
decode bytes to unicode, so you have to watch out for them.
Here we use an ASCII format string, with unicode data. The format
string will be decoded to unicode, then the formatting performed, resulting
in a unicode string.
Next we switch the two: A unicode format string and a byte string again
combine to produce a unicode string, because the byte string data is
decoded as ASCII.
Even just attempting to print a unicode string will cause an implicit
encoding: output is always bytes, so the unicode string has to be encoded
into bytes before it can be printed.
The next one is truly confusing: we ask to encode a byte string to UTF-8,
and get an error about not being about to decode as ASCII! The problem here
is that byte strings can’t be encoded: remember encode is how you turn unicode
into bytes. So to perform the encoding you want, Python 2 needs a unicode
string, which it tries to get by implicitly decoding your bytes as ASCII.
So you asked to encode to UTF-8, and you get an error about decoding ASCII.
It pays to look carefully at the error, it has clues about what operation is
being attempted, and how it failed.
Lastly, we encode an ASCII string to UTF-8, which is silly, encode
should be used on unicode string. To make it work, Python performs the
same implicit decode to get a unicode string we can encode, but since the
string is ASCII, it succeeds, and then goes on to encode it as UTF-8,
producing the original byte string, since ASCII is a subset of UTF-8.
Fact of Life #3
Need to keep them straight
Need to deal with both
This is the most important Fact of Life: bytes and unicode are both
important, and you need to deal with both of them. You can’t pretend
that everything is bytes, or everything is unicode. You need to use
each for their purpose, and explicitly convert between them as needed.
We’ve seen the source of Unicode pain in Python 2, now let’s take
a look at Python 3. The biggest change from Python 2 to Python 3 is
their treatment of Unicode.
str: a sequence of code points (unicode)
bytes: a sequence of bytes
3
>>> my_string = "Hi \u2119\u01b4\u2602\u210c\xf8\u1f24" >>> type(my_string) <class 'str'> >>> my_bytes = b"Hello World" >>> type(my_bytes) <class 'bytes'>
Just as in Python 2, Python 3 has two string types, one for unicode and
one for bytes, but they are named differently.
Now the «str» type that you get from a plain string literal stores unicode,
and the «bytes» types stores bytes. You can create a bytes literal with a b
prefix.
So «str» in Python 2 is now called «bytes,» and «unicode» in Python 2 is
now called «str». This makes more sense than the Python 2 names, since
Unicode is how you want all text stored, and byte strings are only for
when you are dealing with bytes.
Python 3 won’t implicitly change bytes ↔ unicode
3
>>> "Hello " + b"world" Traceback (most recent call last): TypeError: Can't convert 'bytes' object to str implicitly >>> "Hello" == b"Hello" False >>> d = {"Hello": "world"} >>> d[b"Hello"] Traceback (most recent call last): KeyError: b'Hello'
The biggest change in the Unicode support in Python 3 is that there is
no automatic decoding of byte strings. If you try to combine a byte string
with a unicode string, you will get an error all the time, regardless of
the data involved!
All of those operations I showed where Python 2 silently converted byte
strings to unicode strings to complete an operation, every one of them is
an error in Python 3.
In addition, Python 2 considers a unicode string and a byte string
equal if they contain the same ASCII bytes, and Python 3 won’t. A
consequence of this is that unicode dictionary keys can’t be found with
byte strings, and vice-versa, as they can be in Python 2.
Mixing bytes and unicode is always PAIN
You are forced to keep them straight
This drastically changes the nature of Unicode pain in Python 3. In
Python 2, mixing unicode and bytes succeeds so long as you only use ASCII
data. In Python 3, it fails immediately regardless of the data.
So Python 2’s pain is deferred: you think your program is correct, and
find out later that it fails with exotic characters.
With Python 3, your code fails immediately, so even if you are
only handling ASCII, you have to explicitly deal with the difference
between bytes and unicode.
Python 3 is strict about the difference between bytes and unicode.
You are forced to be clear in your code which you are dealing with.
This has been controversial, and can cause you pain.
3
>>> open("hello.txt", "r").read() 'Hello, world!\n' >>> open("hello.txt", "rb").read() b'Hello, world!\n' >>> open("hi_utf8.txt", "r").read() 'Hi \xe2\u201e\u2122\xc6\xb4\xe2\u02dc\u201a\xe2\u201e\u0152\xc3\xb8\xe1\xbc\xa4' >>> open("hi_utf8.txt", "r", . .. encoding=locale.getpreferredencoding()).read() 'Hi \xe2\u201e\u2122\xc6\xb4\xe2\u02dc\u201a\xe2\u201e\u0152\xc3\xb8\xe1\xbc\xa4' >>> open("hi_utf8.txt", "r", encoding="utf-8").read() 'Hi \u2119\u01b4\u2602\u210c\xf8\u1f24' >>> open("hi_utf8.txt", "rb").read() b'Hi \xe2\x84\x99\xc6\xb4\xe2\x98\x82\xe2\x84\x8c\xc3\xb8\xe1\xbc\xa4'
Because of this new strictness, Python 3 has changed how you read files.
Python has always had two modes for reading files: binary and text. In Python 2, it
only affected the line endings, and on Unix platforms, even that was a no-op.
In Python 3, the two modes produce different results. When you open a file in text
mode, either with «r», or by defaulting the mode entirely, the data read from the
file is implicitly decoded into Unicode, and you get str objects.
If you open a file in binary mode, by supplying «rb» as the mode, then the data
read from the file is bytes, with no processing done on them.
The implicit conversion from bytes to unicode uses the encoding returned
from locale.getpreferredencoding(), and it may not give you the results you
expect. For example, when we read hi_utf8.txt, it’s being decoded using
the locale’s preferred encoding, which since I created these samples on
Windows, is «cp1252». Like ISO 8859-1, CP-1252 is a one-byte character
code that will accept any byte value, so it will never raise a
UnicodeDecodeError. That also means that it will happily decode data that
isn’t actually CP-1252, and produce garbage.
To get the file read properly, you should specify an encoding to use.
The open() function now has an optional encoding parameter.
OK, so how do we deal with all this pain? The good news it that the rules
to remember are simple, and they’re the same for Python 2 and Python 3.
Bytes on the outside, unicode on the inside
Encode/decode at the edges
bytes bytes bytes bytes | |
decode | (Library) |
Unicode Unicode Unicode Unicode | |
encode | (Library) |
bytes bytes bytes bytes |
As we saw with Fact of Life #1, the data coming into and going out of
your program must be bytes. But you don’t need to deal with bytes on the
inside of your program. The best strategy is to decode incoming bytes as
soon as possible, producing unicode. You use unicode throughout your
program, and then when outputting data, encode it to bytes as late as
possible.
This creates a Unicode sandwich: bytes on the outside, Unicode on the
inside.
Keep in mind that sometimes, a library you’re using may do some of these
conversions for you. The library may present you with Unicode input, or
will accept Unicode for output, and the library will take care of the edge
conversion to and from bytes. For example, Django provides Unicode, as
does the json module.
Bytes or Unicode?
If bytes, what encoding?
2
>>> print type(my_unicode) <type 'unicode'> >>> print repr(my_unicode) u'Hi \u2119\u01b4\u2602\u210c\xf8\u1f24'
The second rule is, you have to know what kind of data you are dealing with.
At any point in your program, you need to know whether you have a byte string
or a unicode string. This shouldn’t be a matter of guessing, it should be
by design.
In addition, if you have a byte string, you should know what encoding it
is if you ever intend to deal with it as text.
When debugging your code, you can’t simply print a value to see what it
is. You need to look at the type, and you may need to look at the repr of
the value in order to get to the bottom of what data you have.
Fact of Life #4
You cannot infer the encoding of bytes
You must be told, or you have to guess
Content-Type: text/html; charset=ISO-8859-4 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <?xml version="1.0" encoding="UTF-8" ?> # -*- coding: iso8859-1 -*-
I said you have to understand what encoding your byte strings are.
Here’s Fact of Life #4: You can’t determine the encoding of a byte string
by examining it. You need to know through other means. For example,
many protocols include ways to specify the encoding. Here we have
examples from HTTP, HTML, XML, and Python source files. You may
also know the encoding by prior arrangement, for example, the spec
for a data source may specify the encoding.
There are ways to guess at the encoding of the bytes, but they are
just guesses. The only way to be sure of the encoding is to find it
out some other way.
48 | 69 | e2 | 84 | 99 | c6 | b4 | e2 | 98 | 82 | e2 | 84 | 8c | c3 | b8 | e1 | bc | a4 | |
utf-8 | H | i | ℙ | ƴ | ☂ | ℌ | ø | ἤ | ||||||||||
iso8859-1 | H | i | â | | | Æ | ´ | â | | | â | | | Ã | ¸ | á | ¼ | ¤ |
utf-16-le | 楈 | 蓢 | 욙 | | 芘 | 蓢 | 쎌 | | ꒼ | |||||||||
utf-16-be | 䡩 | | 駆 | 듢 | 颂 | | 賃 | 룡 | 벤 | |||||||||
shift-jis | H | i | 邃 | 卮 | エ | 笘 | や | ъ | テ | ク | 眈 | 、 |
Here’s an example of our exotic Unicode string, encoded as UTF-8, and
then mistakenly decoded in a variety of encodings. As you can see, decoding
with an incorrect encoding might succeed, but produce the wrong characters.
Your program can’t tell it’s decoding wrong, only when people try to read
the text will you know something has gone wrong.
This is a good demonstration of Fact of Life #4: the same stream of bytes
is decodable using a number of different encodings. The bytes themselves
don’t indicate what encoding they use.
BTW, there’s a term for this garbage display, from the Japanese who have
been dealing with this for years and years: Mojibake.
Fact of Life #5
Sometimes you are told wrong.
Unfortunately, because the encoding for bytes has to be communicated
separately from the bytes themselves, sometimes the specified encoding is
wrong. For example, you may pull an HTML page from a web server, and the
HTTP header claims the page is 8859-1, but in fact, it is encoded with
UTF-8.
In some cases, the encoding mismatch will succeed and cause mojibake.
Other times, the encoding is invalid for the bytes, and will cause a
UnicodeError of some sort.
ȧƈƈḗƞŧḗḓ ŧḗẋŧ ƒǿř ŧḗşŧīƞɠ
ℛℯα∂α♭ℓℯ ♭ʊ☂ η☺т Ѧ$☾ℐℐ
¡ooʇ ןnɟǝsn sı uʍop-ǝpısdn
It should go without saying: you should explicitly test your Unicode
support. To do this, you need challenging Unicode data to pump through
your code. If you are an English-only speaker, you may have a problem
doing this, because lots of non-ASCII data is hard to read. Luckily, the
variety of Unicode code points mean you can construct complex Unicode
strings that are still readable by English speakers.
Here’s an example of overly-accented text, readable pseudo-ASCII
text, and upside-down text. One good source of these sorts of strings
are various web sites that offer strings like this for teenagers to
paste into social networking sites.
Fact of Life #5½
BOM • Surrogate pairs • Decompositions
Combining marks • Collations • Normalization
Character categories • BiDi • Private use
Ligatures • Character properties
Narrow/Wide • File names • Fonts
Depending on your application, you may need to dig deeper into
the other complexities in the Unicode world. There are many
details that I haven’t covered here, and they can be very involved.
I call this Fact of Life #5½ because you may not have to
deal with any of this.
#1: I/O is always bytes
#2: Need more than 256 symbols
#3: Need both bytes and Unicode
#4: Can’t infer encodings
#5: Declared encodings can be wrong
To review, these are the five unavoidable Facts of Life:
- All input and output of your program is bytes.
- The world needs more than 256 symbols to communicate text.
- Your program has to deal with both bytes and Unicode.
- A stream of bytes can’t tell you its encoding.
- Encoding specifications can be wrong.
#1: Unicode sandwich
#2: Know what you have
#3: Test
These are the three Pro Tips to keep in mind as you build your software
to keep your code Unicode-clean:
- Unicode sandwich: keep all text in your program as Unicode, and convert
as close to the edges as possible. - Know what your strings are: you should be able to explain which of your
strings are Unicode, which are bytes, and for your byte strings, what
encoding they use. - Test your Unicode support. Use exotic strings throughout your test
suites to be sure you’re covering all the cases.
If you follow these tips, you’ll write good solid code that deals
well with Unicode, and won’t fall over no matter how wild the Unicode
it encounters.
Other resources you might find helpful:
Joel Spolsky wrote The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!),
which covers how Unicode works and why. It has no Python-specific information,
but is better written than this talk!
If you need to deal with the semantics of arbitrary Unicode characters, the unicodedata module
in the Python standard library has functions that can help.
For testing Unicode, the various «fancy» text generators
for use on social networks work great.
bit.ly/unipain
☃ U+2603 SNOWMAN |
☠ U+2620 SKULL AND CROSSBONES |
🌎 U+1F30E EARTH GLOBE AMERICAS |
🌏 U+1F30F EARTH GLOBE ASIA-AUSTRALIA |
🐍 U+1F40D SNAKE |
🐝 U+1F41D HONEYBEE |
🐦 U+1F426 BIRD |
👌 U+1F44C OK HAND SIGN |
👍 U+1F44D THUMBS UP SIGN |
👽 U+1F47D EXTRATERRESTRIAL ALIEN |
💥 U+1F4A5 COLLISION SYMBOL |
💩 U+1F4A9 PILE OF POO |
😁 U+1F601 GRINNING FACE WITH SMILING EYES |
😎 U+1F60E SMILING FACE WITH SUNGLASSES |
😞 U+1F61E DISAPPOINTED FACE |
😠 U+1F620 ANGRY FACE |
🙈 U+1F648 SEE-NO-EVIL MONKEY |
🙉 U+1F649 HEAR-NO-EVIL MONKEY |
🙊 U+1F64A SPEAK-NO-EVIL MONKEY |
Unicode HOWTO — документация Python 3.8.6
Определения
Современные программы должны уметь обрабатывать широкий спектр
символы. Приложения часто интернационализированы для отображения
сообщения и вывод на различных языках, выбираемых пользователем; в
той же программе может потребоваться вывести сообщение об ошибке на английском, французском,
Японский, иврит или русский. Веб-контент может быть написан на любом из
эти языки, а также могут включать в себя различные символы эмодзи.
Строковый тип Python использует стандарт Unicode для представления
символов, что позволяет программам Python работать со всеми этими разными
возможные персонажи.
Unicode (https://www.unicode.org/) — это спецификация, направленная на
перечислите все символы, используемые в человеческих языках, и дайте каждому символу
собственный уникальный код. Спецификации Unicode постоянно
переработан и обновлен, чтобы добавить новые языки и символы.
Символ — наименьший возможный компонент текста. «А», «В», «С»,
и т.д., все разные персонажи. Таковы ‘’ и ‘’. Персонажи различаются
в зависимости от языка или контекста, на котором вы говорите
около.Например, для «римской цифры один» есть символ «», то есть
отдельно от заглавной буквы «I». Обычно они выглядят одинаково,
но это два разных символа, которые имеют разные значения.
Стандарт Unicode описывает, как символы представлены
кодовых точек . Значение кодовой точки — это целое число в диапазоне от 0 до
0x10FFFF (около 1,1 миллиона значений, из них около 110 тысяч назначены так
далеко). В стандарте и в этом документе написана кодовая точка
используя обозначение U + 265E
для обозначения символа со значением
0x265e
(9822 в десятичной системе).
Стандарт Unicode содержит множество таблиц, в которых перечислены символы и
их соответствующие кодовые точки:
0061 'а'; ЛАТИНСКАЯ СТРОЧНАЯ БУКВА A 0062 'b'; ЛАТИНСКАЯ СТРОЧНАЯ БУКВА B 0063 'c'; ЛАТИНСКАЯ СТРОЧНАЯ БУКВА C ... 007B '{'; КРОНШТЕЙН ЛЕВЫЙ ... 2167 'Ⅷ'; РИМСКОЕ ЧИСЛО ВОСЕМЬ 2168 'Ⅸ'; РИМСКОЕ ЧИСЛО ДЕВЯТЬ ... 265E '♞'; ЧЕРНЫЙ ШАХМАТНЫЙ РЫЦАРЬ 265F '♟'; ЧЕРНАЯ ШАХМАТНАЯ ПАПКА ... 1F600 '😀'; УЛИЧАЮЩЕЕ ЛИЦО 1F609 '😉'; Подмигивающее лицо ...
Строго говоря, эти определения подразумевают, что бессмысленно говорить «это
символ U + 265E
’. U + 265E
— это кодовая точка, которая представляет собой
персонаж; в данном случае это символ «ЧЕРНЫЙ ШАХМАТНЫЙ РЫЦАРЬ»,
‘♞’. В
неформальных контекстах, это различие между кодовыми точками и символами будет
иногда забывают.
Персонаж представлен на экране или на бумаге набором графических
элементы, которые называются глифом . Глиф для прописной буквы A, например,
это два диагональных штриха и горизонтальный штрих, хотя точные детали будут
зависят от используемого шрифта.Большинству кода Python не нужно беспокоиться о
глифы; определение правильного глифа для отображения обычно является задачей графического интерфейса.
инструментарий или средство визуализации шрифтов терминала.
Кодировки
Подводя итог предыдущему разделу: строка Unicode — это последовательность
кодовые точки, которые представляют собой числа от 0 до 0x10FFFF
(1,114,111
десятичный). Эта последовательность кодовых точек должна быть представлена в
память как набор из кодовых единиц и кодовых единиц затем отображаются
в 8-битные байты.Правила перевода строки Unicode в
последовательность байтов называется кодировкой символов , или просто
кодировка .
Первая кодировка, о которой вы можете подумать, использует 32-битные целые числа в качестве
код, а затем с использованием представления ЦП 32-битных целых чисел.
В этом представлении строка «Python» может выглядеть так:
П о т о н 0x50 00 00 00 79 00 00 00 74 00 00 00 68 00 00 00 6f 00 00 00 6e 00 00 00 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Это простое представление, но его использование дает ряд
проблемы.
Непереносной; разные процессоры по-разному упорядочивают байты.
Очень расточительно места. В большинстве текстов большинство кодовых точек
меньше 127 или меньше 255, поэтому много места занимает0x00
байтов. Приведенная выше строка занимает 24 байта по сравнению с 6 байтами, необходимыми для
Представление ASCII. Увеличенное использование ОЗУ не имеет большого значения (настольный компьютер
компьютеры имеют гигабайты оперативной памяти, и строки обычно не такие большие), но
расширение использования диска и пропускной способности сети в 4 раза — это
невыносимо.Он несовместим с существующими функциями C, такими как
strlen ()
, поэтому новый
необходимо использовать семейство широких строковых функций.
Таким образом, эта кодировка используется нечасто, и люди вместо этого выбирают другую
более эффективные и удобные кодировки, например UTF-8.
UTF-8 — одна из наиболее часто используемых кодировок, а Python часто
по умолчанию использует его. UTF означает «Формат преобразования Unicode»,
а «8» означает, что при кодировании используются 8-битные значения.(Там
также являются кодировками UTF-16 и UTF-32, но реже
используется, чем UTF-8.) UTF-8 использует следующие правила:
Если кодовая точка <128, она представлена соответствующим значением байта.
Если кодовая точка> = 128, она превращается в последовательность из двух, трех или
четыре байта, где каждый байт последовательности находится в диапазоне от 128 до 255.
UTF-8 имеет несколько удобных свойств:
Он может обрабатывать любую кодовую точку Unicode.
Строка Unicode превращается в последовательность байтов, содержащую встроенные
нулевые байты только там, где они представляют собой нулевой символ (U + 0000). Это означает
что строки UTF-8 могут обрабатываться функциями C, такими какstrcpy ()
, и отправляться
через протоколы, которые не могут обрабатывать нулевые байты ни для чего, кроме
маркеры конца строки.Строка текста ASCII также является допустимым текстом UTF-8.
UTF-8 довольно компактен; большинство часто используемых символов могут быть
представлен одним или двумя байтами.Если байты повреждены или потеряны, можно определить начало
следующая кодовая точка в кодировке UTF-8 и повторная синхронизация. Также маловероятно, что
случайные 8-битные данные будут выглядеть как действительный UTF-8.UTF-8 — это байтовая кодировка. Кодировка указывает, что каждый
символ представлен определенной последовательностью из одного или нескольких байтов. Этот
позволяет избежать проблем с порядком байтов, которые могут возникнуть при использовании целых чисел и слов
кодировки, такие как UTF-16 и UTF-32, где последовательность байтов меняется в зависимости от
на оборудовании, на котором была закодирована строка.
Список литературы
На сайте Консорциума Unicode есть таблицы символов,
глоссарий и PDF-версии спецификации Unicode. Будьте готовы к некоторым
трудное чтение. Хронология
происхождение и развитие Unicode также доступно на сайте.
На канале Youtube Computerphile Том Скотт кратко
обсуждает историю Unicode и UTF-8
(9 минут 36 секунд).
Чтобы помочь понять стандарт, Юкка Корпела написал вводную
руководство по чтению
Таблицы символов Юникода.
Еще одна хорошая вводная статья
был написан Джоэлом Спольски.
Если это введение не прояснило вам ситуацию, попробуйте
Прочтите эту альтернативную статью, прежде чем продолжить.
записи в Википедии часто бывают полезны; см., например, записи «кодировка символов» и UTF-8.
Python конвертирует Unicode в строку
Введение
Unicode в Python — это не тема для начинающих. Для лучшего понимания требуется правильное введение.Ради этой публикации мы собираемся предоставить только несколько фрагментов кода, чтобы продемонстрировать преобразование юникода в строку и наоборот. Для получения подробной информации о Unicode в Python рекомендуется прочитать следующую статью. Приступим…
Кодирование против декодирования
При обработке текста кодирование — это преобразование последовательности символов в специальный формат для эффективной обработки, хранения и передачи. Декодирование — это преобразование закодированных данных обратно в исходную форму.Существуют различные схемы кодирования, которые можно использовать. Unicode — король всех, поскольку это стандартная кодировка, используемая в Интернете, операционных системах, браузерах и многом другом.
Юникод
Unicode определяет уникальное целое число (называемое кодовой точкой) для каждого символа. Кодовая точка состоит из одной или нескольких кодовых единиц (единица = 1 байт в UTF-8 или 2 байта в UTF-16). Unicode имеет свои собственные схемы кодирования. Самая популярная схема — UTF-8, которую мы используем в примерах.
Python 2 против Python 3
Существует большая разница между Python 2 и 3 при работе с Unicode, поэтому мы должны быть очень осторожны с терминологией, которую используем. Когда мы говорим «строка», это также Unicode, если мы используем Python 3. В Python 2 строка (называемая str) представляет собой тупой поток байтов, который может быть в любой кодировке, если мы явно не отметим его как Unicode. Возвращаясь к заголовку этого поста, так как это термин, который часто ищут. Есть ли смысл называть юникод строкой? ну, в Python 2.x, процесс кодирования преобразует строку Unicode (например, u «hello») в тип str (str означает байты), но в Python 3.x нет типа данных unicode, вместо этого есть тип str, который по умолчанию является unicode. Итак, в Python 3.x нет преобразования Unicode в строку, однако есть unicode (тип данных str) в байты, который является процессом кодирования. Я настоятельно рекомендую вам ознакомиться с подробной статьей о Unicode, упомянутой ранее (вы также можете найти ее в справочниках).
Кодирование и декодирование в Python
Кодирование в Python — это преобразование кодовой точки в поток байтов.Мы делаем это с помощью функции кодирования. С другой стороны, декодирование — это противоположный процесс, который преобразует поток байтов обратно в кодовые точки. Мы делаем это с помощью функции декодирования. Давайте теперь обманем и скопируем пасту из статьи, упомянутой ранее…
# Определить строку Unicode
х = и’А \ u03BC \ u0394 ‘
печать (х)
печать (введите (x))
печать (len (x))
# Кодировать в байтовый поток
y = x.encode (‘utf-8’)
печать (у)
print (введите (y))
печать (len (y))
# Декодировать байтовый поток обратно в Unicode
г = у.декодировать (‘utf-8’)
печать (z)
печать (введите (z))
печать (len (z))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # Определить строку Unicode x = u’A \ u03BC \ u0394 ‘ print (x) print (type (x)) print (len (x)) # Encode to байтовый поток y = x.encode (‘utf-8’) print (y) print (type (y)) print (len (y)) # Декодировать поток байтов обратно в Unicode z = y.decode (‘utf-8’) print (z) print (type (z)) print (len (z)) |
Если вы запустите приведенный выше фрагмент кода, вы должны получить что-то вроде…
AμΔ
<тип "юникод">
3
AμΔ
<тип 'str'>
5
AμΔ
<тип "юникод">
3
AμΔ <тип 'unicode'> 3 AμΔ <тип 'str'> 5 AμΔ <тип 'unicode'> 3 |
Обратите внимание, что длина исходной строки Unicode (x) равна (3), потому что у нас есть (3) символа в строке, однако длина выходной переменной потока байтов (y) равна (5), потому что у нас есть (5) байтов в байтовом потоке.Очень важно помнить, с каким типом данных мы имеем дело, иначе легко потерять из виду. Если мы запустим тот же код в Python 3.x, мы получим что-то вроде…
AμΔ
<класс 'str'>
3
b’A \ xce \ xbc \ xce \ x94 ‘
<класс 'байты'>
5
AμΔ
<класс 'str'>
3
AμΔ 3 b’A \ xce \ xbc \ xce \ x94 ‘ 5 AμΔ 3 |
Есть ли разница между Python 2.х и 3.х? ДА, вместо типа Unicode у нас есть str, потому что строки в Python 3.x по умолчанию являются Unicode. Что еще? Выходные данные кодирования (поток байтов) выводятся на экран в необработанном формате, что имеет больше смысла, чем в Python 2.x. Если мы посчитаем количество символов, которые начинаются с \ x в приведенном выше выводе, это будет (4), и у нас будет однобайтовая буква (A), поэтому длина закодированного вывода равна (5), а не (3) .
Сводка
- Unicode в Python может сбивать с толку, потому что в Python 2 он обрабатывается по-другому.x против 3.x
- Python 2.x определяет неизменяемые строки типа str для байтовых данных
- Строки Python 3.x (тип str) по умолчанию являются Unicode
- Для кодирования строки Unicode в поток байтов используйте встроенную функцию encode. Встроенная функция decode выполняет обратную операцию.
На сегодня все. Для вопросов и отзывов, пожалуйста, используйте раздел комментариев ниже.
Об авторе
Мохаммед Абуалроб
Инженер-программист @ Cisco
Обработка строк Unicode в Python
В Redis строковые значения могут содержать произвольные двоичные данные, например, вы
может хранить изображение в формате jpeg.Когда вы сохраняете текст в виде строки в Redis и получаете
это, вы получите объект байтов. Если вы хотите вернуть строку Unicode, используйте
decode_responses = True при создании соединения / экземпляра Redis.
Также в Redis нет целочисленного, двойного или логического типа. Они хранятся
как строковое значение. Когда вы сохраняете номер в ключе Redis, вы получаете
строка в байтах или в юникоде. Как видно из примера:
#! / Usr / bin / env python # coding = utf-8 "" "пример redis на python2 "" " импортировать Redis def test_redis (): conn = redis.StrictRedis (хост = 'localhost', порт = 6379, db = 0) conn.set (u'somestring ', u' ✓ правильно ') тип утверждения (conn.get (u'somestring ')) - str assert conn.get (u'somestring ') == b'✓ правильно # нестроковых типов conn.set (u'someint ', 123) тип утверждения (conn.get (u'someint ')) - str assert conn.get (u'someint ') == b'123' conn.set (u'somedouble ', 123.1) тип утверждения (conn.get (u'somedouble ')) - str assert conn.get (u'somedouble ') == b'123.1' conn.set (u'somebool ', True) # не делайте этого.тип утверждения (conn.get (u'somebool ')) - str assert conn.get (u'somebool ') == b'True' conn.hset (u "somehash", "key1", '✓ правильно') conn.hset (u "somehash", "key2", '❌ неправильно') d = conn.hgetall (u "somehash") утверждать "key1" в d утверждать u'key1 'в d тип утверждения (d ['key1']) - байты assert d ['key1'] == u'✓ правильный '. encode (' utf-8 ') assert d ['key1']! = u '✓ правильно' def test_redis_auto_decode (): conn = redis.StrictRedis (host = 'localhost', порт = 6379, db = 0, decode_responses = True) соед.set (u'somestring ', u' ✓ правильно ') тип утверждения (conn.get (u'somestring ')) - это юникод assert conn.get (u'somestring ') == u'✓ правильно # нестроковых типов conn.set (u'someint ', 123) тип утверждения (conn.get (u'someint ')) является юникодом assert conn.get (u'someint ') == u'123' conn.set (u'somedouble ', 123.1) тип утверждения (conn.get (u'somedouble ')) является юникодом assert conn.get (u'somedouble ') == u'123.1' conn.hset (u "somehash", "key1", '✓ правильно') conn.hset (u "somehash", "key2", '❌ неправильно') d = соед.hgetall (у "somehash") утверждать "key1" в d утверждать u'key1 'в d тип утверждения (d ['key1']) - Unicode assert d ['key1'] == u'✓ правильно ' assert d ['key1']! = u '✓ правильно'. кодировать ('utf-8')
В python3 все становится немного неприятно. В python3 ключи и значения redis
строго байты. Это особенно сложно при работе с хешами.
#! / Usr / bin / env python3 # coding = utf-8 "" "пример redis на python3 "" " импортировать Redis def test_redis (): conn = redis.StrictRedis (host = 'localhost', порт = 6379, db = 0) соед.set ('somestring', '✓ правильно') тип утверждения (conn.get ('somestring')) - байты assert conn.get ('somestring') == '✓ правильно'.encode (' utf-8 ') # нестроковых типов conn.set ('что-то', 123) тип утверждения (conn.get ('someint')) - байты assert conn.get ('someint') == b'123 ' conn.set ('некоторая двойка', 123.1) тип утверждения (conn.get ('somedouble')) - байты assert conn.get ('somedouble') == b'123.1 ' conn.set ('somebool', True) # не делайте этого. тип утверждения (conn.get ('somebool')) - байты утверждать конн.получить ('somebool') == b'True ' conn.hset (u "somehash", "key1", '✓ правильно') conn.hset (u "somehash", "key2", '❌ неправильно') d = conn.hgetall (u "somehash") утверждать "key1" не в d утверждать b'key1 'в d тип утверждения (d [b'key1 ']) - байты assert d [b'key1 '] ==' ✓ правильно '. encode (' utf-8 ') def test_redis_auto_decode (): conn = redis.StrictRedis (host = 'localhost', порт = 6379, db = 0, decode_responses = True) conn.set ('somestring', '✓ правильно') тип утверждения (соед.get ('somestring')) равно str assert conn.get ('somestring') == '✓ правильно' # нестроковых типов conn.set ('что-то', 123) тип утверждения (conn.get ('someint')) - str assert conn.get ('someint') == '123' conn.set ('некоторая двойка', 123.1) тип утверждения (conn.get ('somedouble')) - str assert conn.get ('somedouble') == '123.1' conn.hset ("somehash", "key1", '✓ правильно') conn.hset ("somehash", "key2", '❌ неправильно') d = conn.hgetall ("somehash") утверждать "key1" в d утверждать b'key1 'not in d тип утверждения (d ['key1']) - str assert d ['key1'] == u'✓ правильно '
Python: Учебное пособие по Unicode 🐍
Автор Xah Lee.Дата: . Последнее обновление: .
Кодировка исходного кода Python
Какая кодировка исходного кода Python используется по умолчанию?
Для Python 3.x это UTF-8.
Для Python 2.x это ASCII.
[см. таблицу ASCII]
Python 2: Если ваш исходный код содержит символы, отличные от ASCII, вы должны объявить кодировку файла в первой или второй строке, например:
- * - кодировка: utf-8 - * -
x = u "я ♥ кошки" печать x
Объявление # - * - coding: utf-8 - * -
в первой строке — это соглашение, принятое от текстового редактора Emacs.Он сообщает любой программе, читающей файл, что файл закодирован с использованием определенной кодировки.
Если вы не знаете Unicode, прочтите сначала:
Основы Unicode: набор символов, кодировка, UTF-8, кодовая точка
См. Также:
Юникод в Python 3
Строка Python 3 — это последовательность символов Юникода.
В Python 3 все в Юникоде (UTF-8). Вам не нужно ни # - * - кодировка: utf-8 - * -
, и u "…"
.
Python 3 поддерживает Unicode в именах переменных и функций.
def ƒ (n): вернуть n + 1 α = 4 печать (ƒ (α))
Обратите внимание, Unicode, которые не являются буквами, не допускаются.
♥ = 4 печать (♥)
Python 2: объявить строку Unicode
Для Python 2 строки, содержащие символы Юникода, должны начинаться с и
перед строкой.
Для Python 3 любая строковая кавычка может начинаться с u
, например: u "xyz"
, но это не имеет значения. Любая строка уже является типом данных Unicode.
aa = u "Я ♥ U" печать aa
u
делает строку типом данных Unicode. Без и
строка представляет собой просто последовательность байтов.
Иногда, когда вы печатаете строки Unicode, вы можете получить такую ошибку:
UnicodeEncodeError: кодек ascii не может кодировать символ u '\ u03b1' в позиции 16: порядковый номер не в диапазоне (128).
Решение — использовать метод .encode ()
или .decode ()
.
myStr = u'α ' напечатать 'греческий альфа:', myStr выведите 'Greek alpha:', myStr.кодировать ('utf-8')
Escape-последовательность Unicode в строке
И python 3, и python 2 могут содержать символы Unicode буквально в строке.
например,
"i ♥ u"
или
У "Я ♥ У"
.
Вы также можете использовать escape-последовательности. Есть 2 формы:
-
\ u 4_digits_hex
→ для символа, код Юникода которого может быть выражен в 4 шестнадцатеричных десятичных разрядах. Если меньше 4 цифр, добавьте 0 впереди. -
\ U 8_digits_hex
→ для символа, код Юникода которого больше 4 шестнадцатеричных десятичных знаков.Если шестнадцатеричные цифры символа меньше 8 цифр, вы должны добавить 0 впереди, чтобы в сумме получилось 8 цифр.
x = "♥" y = "\ u2665" печать (x == y) x = "😸" y = "\ U0001f638" печать (x == y)
х = и "♥" y = u "\ u2665" напечатать x == y х = и "😸" y = u "\ U0001f638" напечатать x == y
Python 2: Юникод в регулярном выражении
При использовании регулярного выражения в строке Unicode, и вы хотите, чтобы
шаблоны слов { \ w
, \ W
} и образцы границ { \ b
, \ B
},
в зависимости от свойств символа Unicode вам необходимо добавить флаг Unicode re.\ u0000->] + ", сс)
если myResult:
распечатать myResult else:
печать "нет совпадения"
Найти имя символа Unicode, кодовую точку, свойства
Python: получить имя Unicode, кодовую точку
Преобразовать кодировку файла
Python: преобразование кодировки файлов
Поиск символов Unicode
Поиск в Юникоде 😄
[см. Основы Unicode: набор символов, кодировка, UTF-8]
Если у вас есть вопрос, положите 5 долларов на patreon и напишите мне.
Unicode - pysheeet
Основная цель этой шпаргалки - собрать некоторые общие фрагменты, которые
связанные с Unicode. В Python 3 строки представлены Unicode вместо
байтов. Дополнительную информацию можно найти на PEP 3100
.
Код ASCII - наиболее известный стандарт, определяющий числовые коды
для персонажей. Числовые значения изначально определяют только 128 символов,
поэтому ASCII содержит только управляющие коды, цифры, строчные буквы, прописные буквы
буквы и т. д.Однако нам недостаточно представить такие символы, как
акцентированные иероглифы, китайские иероглифы или эмодзи существовали во всем мире.
Поэтому для решения этой проблемы был разработан Unicode . Он определяет
кодовая точка для представления различных символов, таких как ASCII, но количество
символов до 1,111,998.
Строка
В Python 2 строки представлены в байтах , а не в Unicode . Python предоставляет
различные типы строк, такие как строка Unicode, необработанная строка и т. д.В этом случае, если мы хотим объявить строку Unicode, мы добавляем префикс u
для
строковые литералы.
>>> s = 'Café' # байтовая строка >>> с 'Кафе \ xc3 \ xa9' >>> тип (ы) <тип 'str'> >>> u = u'Café '# строка в Юникоде >>> ты u'Caf \ xe9 ' >>> тип (u) <тип "юникод">
В Python 3 строки представлены в Unicode . Если мы хотим представить
байтовой строки, мы добавляем префикс b
для строковых литералов.Обратите внимание, что ранние
Версии Python (3.0–3.2) не поддерживают префикс u
. Чтобы облегчить
боль при переносе приложений, поддерживающих Unicode, с Python 2, Python 3.3 один раз
снова поддерживает префикс и
для строковых литералов. Дополнительная информация может
можно найти на PEP 414
>>> s = 'Кафе' >>> тип (ы) <класс 'str'> >>> с 'Кафе' >>> s.encode ('utf-8') b'Caf \ xc3 \ xa9 ' >>> s.encode ('utf-8'). decode ('utf-8'). 'Кафе'
Функции Python encode () и decode ()
Общие селекторы
Только точные совпадения
Только точное совпадение
Искать в заголовке
Искать в названии
Искать в содержании
Искать в содержании
Искать в отрывке
Искать в сообщениях
Искать в сообщениях
Искать на страницах
Искать на страницах
- Дом
- Начните здесь
wb_sunny
.