В чем разница между кодированием / декодированием?


180

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

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

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

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

РЕДАКТИРОВАТЬ:

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


Я думаю, что второй ответ на этой странице достаточно ясен и лаконичен.
— Бен

Ответы:


106

decodeМетод Юникода строк действительно не имеет каких - либо приложений на всех (если у вас есть какие - то не-текстовые данные в юникод строку для какой - то причине - см . Ниже) Я думаю, что в основном это происходит по историческим причинам. В 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, это больше не проблема.


4
.decode()на строки Юникода могут быть полезны, например,print u'\\u0203'.decode('unicode-escape')
— JFS

Хороший пример @JFSebastian в python3 Я думаю, вы бы сделали:print u'\\u0203'.encode('utf8').decode('unicode-escape')
— AJP

1
@AJP: на Python 3:codecs.decode(u'\\u0203', 'unicode-escape')
— JFS

@hop: да. Чтобы обнаружить неверный ввод и для совместимости с Python 2/3, строка может быть явно закодирована с использованием asciiкодировки:\\u0203\u00e4'.encode('ascii').decode('unicode-escape')
— jfs

@hop: ваш первый комментарий (почему вы удалили его? Не удаляйте комментарии, на которые были даны ответы) уже сказал это. Мой ответ ( .encode('ascii').decode('unicode-escape')) не зависит от sys.getdefaultencoding().
— Jfs

71

Представление строки Юникода в виде строки байтов называется кодированием . Использование 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» не может кодировать символы в позиции 0-5: 
    порядковый номер вне диапазона (128)

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

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

Пример:

   >>> Вы
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5' # интерпретатор печатает объект Unicode следующим образом
   >>> Юникод ('\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5', 'latin1')
   и '\ xc3 \ xa6 \ xc3 \ XB8 \ xc3 \ xa5'
   >>> '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'.decode (' latin1 ')
   и '\ xc3 \ xa6 \ xc3 \ XB8 \ xc3 \ xa5'

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

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

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


6
Вы не ответили на вопрос ОП. ОП хочет знать, что делают str.encode () и unicode.decode (). Вы только что повторили то, что было сказано в исходном вопросе.
— Stuckintheshuck

Отличный ответ, почему на практике вы когда-нибудь связывались с декодированием и кодированием. Не каждая машина понимает один и тот же набор символов, но все они понимают байты. Кодирование в байты для языка, который универсальные компьютеры понимают (и может быть перенесено или сохранено на диск), но декодируется, когда люди действительно должны прочитать эти байты (например, на стороне клиента).
— Алекс Петралия

Фантастический ответ! Это должно идти вверх!
— sandyp

16

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

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


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

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

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

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

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


12

mybytestring.encode (somecodec) имеет смысл для следующих значений somecodec:

  • base64
  • BZ2
  • Zlib
  • наговор
  • quopri
  • rot13
  • string_escape
  • уу

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


5

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

Редактировать:

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

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

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


1
-1: метод декодирования не применяется к объекту Unicode. Вместо этого объект unicode кодируется как строка байтов 'ascii', прежде чем начнется операция декодирования. Для доказательства этого утверждения попробуйте u'ã'.decode ('hex') - который приводит к UnicodeEncodeError
— nosklo

2
@nosklo: Вы правы. Что я действительно имел в виду, так это то, что у объектов Юникода есть метод decode (), так что вы также можете применять к ним кодировки не-кодировки символов. Весь этот бизнес, не связанный с кодировкой символов, делает этот интерфейс беспорядочным в Python <3

1

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

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

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

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.