В чем разница между кодированием/декодированием?
Я никогда не был уверен, что понимаю разницу между декодированием str/unicode и кодированием.
Я знаю, что str().decode()
для тех случаев, когда у вас есть строка байтов, которые, как вы знаете, имеют определенную кодировку символов, учитывая, что имя кодировки возвращает строку юникода.
Я знаю, что unicode().encode()
преобразует символы unicode в строку байтов в соответствии с заданным именем кодировки.
Но я не понимаю, для чего предназначены str().encode()
и unicode().decode()
. Может ли кто-нибудь объяснить, и, возможно, также исправить что-нибудь еще, что я получил неправильно?
EDIT:
Несколько ответов дают информацию о том, что .encode
делает для строки, но никто не знает, что делает .decode
для юникода.
Ответы
Ответ 1
Метод строк unicode decode
действительно не имеет каких-либо приложений вообще (если у вас есть некоторые нетекстовые данные в строке 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()
также лишний.
Но есть другое применение последнего метода, который полезен: есть encodings, которые ничего не имеют делать с наборами символов и, следовательно, можно применять к 8-битным строкам значимым образом:
>>> s.encode('zip')
'x\x9c;\xbc\r\x00\x02>\x01z'
Вы правы, хотя: двусмысленное использование "кодирования" для обоих этих приложений... awkard. Опять же, с отдельными типами byte
и string
в Python 3, это уже не проблема.
Ответ 2
Чтобы представить строку unicode в виде строки байтов, называется encoding. Используйте 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('...', 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, поэтому выше, вероятно, неверно для python 3.
Некоторые хорошие ссылки:
Ответ 3
mybytestring.encode(somecodec) имеет смысл для этих значений somecodec
:
- base64
- BZ2
- Zlib
- шестигранной
- quopri
- rot13
- string_escape
- уу
Я не уверен, что подходит декодирование уже декодированного текста в Юникоде. Попытка, что с любой кодировкой, кажется, всегда пытается сначала кодировать кодировку по умолчанию системы.
Ответ 4
anUnicode. encode ('encoding') приводит к объекту string и может быть вызван в объект unicode
aString. декодировать ('encoding') приводит к объекту unicode и может быть вызван в строку, закодированную в данной кодировке.
Несколько дополнительных объяснений:
Вы можете создать некоторый объект unicode, который не имеет никакого набора кодировок. Способ, которым он хранится в памяти Python, никоим образом не беспокоит вас. Вы можете выполнить поиск, разделить его и вызвать любую функцию управления строкой, которая вам нравится.
Но настало время, когда вы хотите напечатать объект юникода для консоли или в каком-то текстовом файле. Таким образом, вы должны закодировать его (например, в UTF-8), вы вызываете encode ('utf-8') и получаете строку с '\ u <someNumber> ' внутри, что идеально подходит для печати.
Затем снова - вы хотели бы сделать обратное - прочитать строку, закодированную в UTF-8, и рассматривать ее как Юникод, поэтому \u360 будет одним символом, а не 5. Затем вы декодируете строка (с выбранной кодировкой) и получить новый объект типа unicode.
В качестве побочного примечания вы можете выбрать некоторую извращенную кодировку, например, "zip", "base64", "rot", а некоторые из них будут конвертировать из строки в строку, но я считаю, что наиболее распространенным случаем является тот, который включает UTF-8/UTF-16 и строка.
Ответ 5
Вы должны прочитать Python UnicodeDecodeError - я ошибаюсь в кодировке. Мое понимание юникода в Python было намного яснее после прочтения принятого ответа.
Ответ 6
Существует несколько кодировок, которые можно использовать для де-/кодирования с str на str или из unicode в unicode. Например base64, hex или даже rot13. Они перечислены в модуле кодеков.
Edit:
Сообщение декодирования строки unicode может отменить соответствующую операцию кодирования:
In [1]: u'0a'.decode('hex')
Out[1]: '\n'
Возвращаемый тип - это str вместо unicode, что, к сожалению, на мой взгляд. Но когда вы не делаете надлежащего en-/decode между str и unicode, это все равно похоже на беспорядок.