Есть ли вред кодированию (с одним и тем же форматом кодирования) строки несколько раз? (в Python) - PullRequest
1 голос
/ 12 декабря 2010

Есть ли какой-нибудь вред кодированию строки в Python несколько раз с одинаковым форматом кодирования? (т. е. UTF-8)?

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

Это может измениться в будущем, и кто-то может решить использовать его в другой (или такой) функции сериализации, без предварительного кодирования его результата в UTF-8. Мне интересно, безопасно ли всегда возвращать из него строку в кодировке UTF-8 (эта строка также будет повторно переписана .encode () функцией сериализации в данный момент). Мои тесты показывают, что это не проблема, но я решил спросить.

Спасибо!

Ответы [ 4 ]

5 голосов
/ 12 декабря 2010

Вы не можете кодировать несколько раз, это не работает.

>>> s = u"ä".encode('latin1')
>>> s = s.encode('latin1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

Видите, вы получаете "кодек ascii не может декодировать". Метод кодирования для строки состоит в том, что сначала декодирует строку в Unicode, а затем снова кодирует ее с заданной кодировкой. Он будет декодировать его с помощью системной кодировки, которая по умолчанию является ascii.

Такое поведение является неожиданным и исчезло в Python 3, кстати, где байты не имеют метода кодирования, а строки не имеют метода декодирования.

Так что вы просто не можете кодировать его несколько раз, и, конечно, это потому, что кодирование кодированной строки просто не имеет никакого смысла. Кодировка конвертирует из Unicode в двоичное представление, и вы не можете далее кодировать двоичное представление.

1 голос
/ 12 декабря 2010

В общем, вы должны вызывать encode только для unicode объектов и только decode для string объектов.

encode кодирует объект Unicode в заданную кодировку (хранится в виде строки). decode декодирует заданную кодировку обратно в объект Unicode.

Существование string.encode и unicode.decode в 2.x следует рассматривать как исторический артефакт.

1 голос
/ 12 декабря 2010

Если строка не является чистой ASCII, тогда да, это может причинить вред (и если это ASCII чистой, вам не нужно беспокоиться о UTF-8):

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

Это хорошая практика длятрактовать последовательности байтов и текст как две разные вещи.В Python 3 это разные вещи: байтовые объекты имеют метод decode(), а строковые (Unicode) объекты имеют метод encode().

0 голосов
/ 12 декабря 2010

Что ж, если у вас есть поток байтов, которые представляют собой текст в кодировке UTF-8, и вы интерпретируете их как строку, закодированную во что-то еще, а затем перекодируете ее как UTF-8, тогда у вас есть проблема.*

Если вы снова прочитаете его как UTF-8 (поскольку вы, конечно, не можете обрабатывать байты как текст без кодировки), то у вас будет Unicode, который при повторном написании как UTF-8 будет выглядеть так же, как и раньше.

Только будьте осторожны, чтобы не слишком возиться с кодировками.Распространенной ошибкой является интерпретация текста в кодировке UTF-8 как латинского 1, что превращает Fööbär в Fööbär, что, конечно, больше не изменится.

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

...