В чем разница между кодированием / декодированием? - PullRequest
171 голосов
/ 15 января 2009

Я никогда не был уверен, что понимаю разницу между декодированием str / unicode и кодированием.

Я знаю, что str().decode() для случаев, когда у вас есть строка байтов, которая, как вы знаете, имеет определенную кодировку символов, при условии, что имя кодировки вернет строку Unicode.

Я знаю, что unicode().encode() преобразует символы Unicode в строку байтов в соответствии с заданным именем кодировки.

Но я не понимаю, для чего str().encode() и unicode().decode(). Может кто-нибудь объяснить, а возможно и исправить что-то еще, что я ошибся выше?

EDIT:

Несколько ответов дают информацию о том, что .encode делает со строкой, но никто, кажется, не знает, что .decode делает для юникода.

Ответы [ 7 ]

101 голосов
/ 16 января 2009

Метод decode для строк Unicode на самом деле вообще не имеет приложений (если у вас по какой-то причине нет нетекстовых данных в строке Unicode - см. Ниже). Я думаю, что в основном это происходит по историческим причинам. В Python 3 это полностью исчезло.

unicode().decode() будет выполнять неявное кодирование из s с использованием кодека по умолчанию (ascii). Проверьте это так:

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

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

Сообщения об ошибках точно такие же.

Для str().encode() все наоборот - он пытается неявное декодирование из s с кодировкой по умолчанию:

>>> s = 'ö'
>>> s.decode('utf-8')
u'\xf6'
>>> s.encode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0:
ordinal not in range(128)

При таком использовании str().encode() также является излишним.

Но есть другое применение последнего метода, который полезен: есть кодировки , которые не имеют ничего общего с наборами символов и, таким образом, могут применяться к 8-битным строкам осмысленно:

>>> s.encode('zip')
'x\x9c;\xbc\r\x00\x02>\x01z'

Вы правы, хотя: неоднозначное использование "кодирования" для обоих этих приложений ... удивительно. Опять же, с отдельными типами byte и string в Python 3, это больше не проблема.

68 голосов
/ 15 января 2009

Представление строки Юникода в виде строки байтов известно как кодировка . Используйте u'...'.encode(encoding).

Пример:

    >>> u'æøå'.encode('utf8')
    '\xc3\x83\xc2\xa6\xc3\x83\xc2\xb8\xc3\x83\xc2\xa5'
    >>> u'æøå'.encode('latin1')
    '\xc3\xa6\xc3\xb8\xc3\xa5'
    >>> u'æøå'.encode('ascii')
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: 
    ordinal not in range(128)

Обычно вы кодируете строку Unicode всякий раз, когда вам нужно использовать ее для ввода-вывода, например, передавать ее по сети или сохранять в файл на диске.

Для преобразования строки байтов в строку Unicode известен как decoding . Используйте unicode('...', encoding) или '...'. Decode (encoding).

Пример:

   >>> u'æøå'
   u'\xc3\xa6\xc3\xb8\xc3\xa5' # the interpreter prints the unicode object like so
   >>> unicode('\xc3\xa6\xc3\xb8\xc3\xa5', 'latin1')
   u'\xc3\xa6\xc3\xb8\xc3\xa5'
   >>> '\xc3\xa6\xc3\xb8\xc3\xa5'.decode('latin1')
   u'\xc3\xa6\xc3\xb8\xc3\xa5'

Обычно вы декодируете строку байтов всякий раз, когда вы получаете строковые данные из сети или из файла на диске.

Я полагаю, что в Python 3 есть некоторые изменения в обработке Unicode, поэтому вышеприведенное, вероятно, не правильно для Python 3.

Несколько хороших ссылок:

15 голосов
/ 17 января 2009

anUnicode. encode ('encoding') приводит к объекту string и может вызываться для объекта unicode

aString. decode ('encoding') приводит к объекту unicode и может вызываться в строке, закодированной в данной кодировке.


Еще несколько объяснений:

Вы можете создать какой-нибудь объект в кодировке Юникод, для которого не задана какая-либо кодировка. То, как он хранится в памяти Python, не имеет значения. Вы можете искать его, разбивать его и вызывать любые функции, которые вам нравятся.

Но наступает момент, когда вы хотите распечатать объект Unicode на консоли или в каком-либо текстовом файле. Таким образом, вы должны кодировать его (например, в UTF-8), вы вызываете кодирование ('utf-8') и вы получаете строку с '\ u ' внутри, что совершенно версия для печати. ​​

Затем, опять же - вы хотели бы сделать обратное - прочитать строку, закодированную в UTF-8, и трактовать ее как Unicode, так что \ u360 будет одним символом, а не 5. Тогда вы декодируете строка (с выбранной кодировкой) и получение нового объекта типа Unicode.

Так же, как примечание - вы можете выбрать некоторую извращенную кодировку, такую ​​как 'zip', 'base64', 'rot', и некоторые из них будут конвертировать из строки в строку, но я считаю, что наиболее распространенным случаем является тот, который включает UTF-8 / UTF-16 и строка.

12 голосов
/ 15 января 2009

mybytestring.encode (somecodec) имеет значение для этих значений somecodec:

  • base64
  • BZ2
  • Zlib
  • шестигранный
  • quopri
  • rot13
  • string_escape
  • уу

Я не уверен, для чего подходит декодирование уже декодированного текста Unicode. Попытка сделать это с любой кодировкой, кажется, всегда сначала пытается кодировать с использованием кодировки системы по умолчанию.

8 голосов
/ 16 января 2009

Вы должны прочитать Python UnicodeDecodeError - Я неправильно понимаю, закодировать . Мое понимание юникода в Python стало намного понятнее после прочтения принятого ответа.

5 голосов
/ 15 января 2009

Существует несколько кодировок, которые можно использовать для де-кодирования из str в str или из unicode в unicode. Например, base64, hex или даже rot13. Они перечислены в модуле кодеков .

Edit:

Сообщение декодирования в строке Unicode может отменить соответствующую операцию кодирования:

In [1]: u'0a'.decode('hex')
Out[1]: '\n'

Возвращаемый тип str вместо unicode, что, на мой взгляд, неудачно. Но если вы не выполняете правильное кодирование / декодирование между str и unicode, это все равно выглядит как беспорядок.

0 голосов
/ 03 января 2018

Простой ответ заключается в том, что они полностью противоположны друг другу.

компьютер использует базовую единицу байта для хранения и обработки информации, это бессмысленно для человеческого глаза.

например, '\ xe4 \ xb8 \ xad \ xe6 \ x96 \ x87' - это представление двух китайских символов, но компьютер знает (что означает печать или хранение), что это китайские иероглифы, когда они получают словарь для ищите это китайское слово, в данном случае это словарь "utf-8", и оно не сможет правильно отобразить намеченное китайское слово, если вы загляните в другой или неправильный словарь (используя другой метод декодирования).

В приведенном выше случае процесс поиска компьютером китайского слова - это декодирование ().

И процесс компьютерной записи китайцев в память компьютера кодируется ().

поэтому информация о кодировании - это необработанные байты, а декодированная информация - это необработанные байты и имя словаря для ссылки (но не самого словаря).

...