Чим відрізняється кодування / декодування?


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()на рядок Unicode можуть бути корисні, наприклад,print u'\\u0203'.decode('unicode-escape')
jfs

Хороший приклад @JFSebastian in 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

Для представлення рядка unicode як рядка байтів відомо як кодування . Використовуйте 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)або "..." декодування (кодування).

Приклад:

   >>> u'æøå '
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5' # інтерпретатор друкує об'єкт unicode так
   >>> 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.

Деякі хороші посилання:


6
Ви не відповіли на питання ОП. ОП хоче знати, що роблять str.encode () та unicode.decode (). Ви просто повторили те, що було сказано в оригінальному запитанні.
stuckintheshuck

Чудова відповідь, чому на практиці ви ніколи не возилися з розшифровкою та кодуванням. Не кожна машина розуміє однаковий набір символів, але всі вони розуміють байти. Кодуйте в байти для мовних комп'ютерів, які в цілому розуміють (і можуть бути перенесені або збережені на диск), але декодують, коли люди насправді повинні читати ці байти (наприклад, на стороні клієнта).
Алекс Петралія

Фантастична відповідь! Це повинно подорожчати !!
пісок

16

anUnicode. encode ('кодування') призводить до об'єкта рядка і може бути викликаний об'єктом unicode

aString. декодування ('кодування') призводить до об'єкта unicode і може бути викликано на рядок, кодованому в заданому кодуванні.


Ще кілька пояснень:

Ви можете створити якийсь об’єкт unicode, який не має жодного набору кодування. Те, як зберігається Python в пам'яті, не викликає ваших проблем. Ви можете шукати його, розділяти його і викликати будь-яку функцію маніпулювання рядком, яка вам подобається.

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

Потім, знову ж - ви хотіли б зробити навпаки - читати рядок , закодовану в UTF-8 і розглядати його як Unicode, так що \ U360 буде один символ, а НЕ 5. Тоді ви декодувати рядок (з обраної кодуванням) і отримати абсолютно новий об’єкт типу unicode.

Як бічна примітка - ви можете вибрати деяке перекручене кодування, наприклад, "zip", "base64", "гниль", а деякі з них перетворяться з рядка в рядок, але я вважаю, що найпоширеніший випадок - той, що включає UTF-8 / UTF-16 і рядок.


12

mybytestring.encode (деякий codec) має значення для цих значень somecodec:

  • база64
  • bz2
  • зліб
  • шестигранний
  • квопри
  • гниль13
  • string_escape
  • uu

Я не впевнений, для чого добре розшифровувати вже розшифрований текст Unicode. Намагаючись, що з будь-яким кодуванням, схоже, завжди спершу намагаються кодувати кодування за замовчуванням у системі.


5

Є кілька кодувань, які можна використовувати для де- / кодування від str до str чи від unicode до unicode. Наприклад, base64, hex або навіть гниль13. Вони перераховані в модулі кодеків .

Редагувати:

Повідомлення декодування в рядку unicode може скасувати відповідну операцію кодування:

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

Повернутий тип - це str замість unicode, на жаль, на мою думку. Але коли ви не робите належного en- / декодування між str та unicode, це все одно виглядає безладом.


1
-1: Метод декодування не застосовується до об’єкта unicode. Натомість об'єкт unicode кодується як тест 'ascii' перед тим, як розпочнеться операція декодування. Для підтвердження цього твердження спробуйте u'ã'.decode ('hex') - це дає UnicodeEncodeError
nosklo

2
@nosklo: Ви маєте рацію. Я дійсно мав на увазі, що об’єкти Unicode мають метод 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.