Проблема кодирования строки Python - PullRequest
2 голосов
/ 30 января 2012

Я использую API Amazon MWS, чтобы получить отчет о продажах для моего магазина, а затем сохранить этот отчет в таблице в базе данных.К сожалению, я получаю ошибку кодирования при попытке закодировать информацию в Unicode.После просмотра отчета (именно так, как его отправил amazon), я увидел строку, в которой находится покупатель:

'S�o Paulo'

, поэтому япопытался закодировать его так:

encodeme = 'S�o Paulo'
encodeme.encode('utf-8)

, но получил следующую ошибку

UnicodeDecodeError: кодек «ascii» не может декодировать байт 0xef в позиции 1: порядковый номер не в диапазоне(128)

Вся причина, по которой я пытаюсь его закодировать, заключается в том, что как только Django видит символ , он выдает предупреждение и обрезает строку, означая, что местоположение сохраненокак S вместо

Сан-Паулу

Любая помощь приветствуется.

Ответы [ 3 ]

4 голосов
/ 30 января 2012

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

s = s.decode('utf-8')

Однако вам необходимо знать, какую кодировку использовать. Входные данные могут поступать в других кодировках, которые utf-8.

Полученная вами ошибка UnicodeDecodeError означает, что ваш объект не является юникодом, это строка байта. Когда вы делаете bytestring.encode, строка сначала декодируется в объект Unicode с кодировкой по умолчанию (ascii), и только затем она кодируется с помощью utf-8.

Я попытаюсь объяснить разницу unicode string и utf-8 bytestring в python.

unicode - это тип данных python, представляющий строку в юникоде. Вы используете Unicode для большинства строковых операций в вашей программе. Python, вероятно, использует utf-8 во внутренних органах, хотя это может быть и utf-16, и это не имеет значения для вас.

bytestring - двоичная безопасная строка. Это может быть любая кодировка. Когда вы получаете данные, например, открываете файл, вы получаете строку байтов, и в большинстве случаев вам захочется декодировать ее в Unicode. Когда вы пишете в файл, вы должны кодировать объекты Unicode в строки байтов. Иногда декодирование / кодирование выполняется за вас фреймворком или библиотекой. Однако не всегда фреймворк может сделать это, потому что не всегда фреймворк может знать, какую кодировку использовать.

utf-8 - это кодировка, которая может правильно представлять любую строку Юникода в качестве строки байтов. Однако вы не можете декодировать любые типы строк с помощью utf-8 в unicode. Вам нужно знать, какая кодировка используется в строке байтов для ее декодирования.

3 голосов
/ 30 января 2012

Похоже, у вас какая-то проблема с кодировкой.

Во-первых, вы должны быть очень уверены, какую кодировку использует Amazon в теле отчета, которое они вам отправляют. Это UTF-8? Это ISO 8859-1? Что-то еще?

К сожалению, Документация по API Amazon MWS Reports , особенно их Справочник по API , пока не очень подходит к тому, какую кодировку они используют. Они упоминают только кодировку UTF-8, так что это должно быть ваше первое предположение. Документация API GetReport (стр.36-37) описывает элемент ответа Report как тип xs:string, но я не вижу, где они определяют этот тип данных. Может быть, они означают тип XML-схемы string тип данных .

Итак, я предлагаю вам сохранить байтовую последовательность, которую вы получаете как тело отчета от Amazon, в файле с нулевыми преобразованиями. Помните, что ваш код, который вызывает AWS, может непреднамеренно изменить строку тела отчета. Изучите байты не ASCII в этом файле с помощью двоичного редактора. Сохраняется ли «São» из «São» как S\xC3\xA3o, что указывает на кодировку UTF-8? Или он хранится как S\xE3o, что указывает на кодировку ISO 8859-1 ?

Я предполагаю, что вы получите свой отчет в виде простого файла. В документации Amazon AWS говорится, что вы можете запросить отчеты, которые будут доставлены вам в формате XML. Это даст вам преимущество, предоставив вам ответ с явным объявлением кодировки.

Как только вы узнаете кодировку тела отчета, теперь вам нужно правильно обработать его. Вы подразумеваете, что используете фреймворк Django и код языка Python для получения отчета от Amazon AWS.

Одна вещь, которая должна стать очень ясной (как объясняет Скирмантас):

  • Строки Unicode содержат символы. Строки байтов содержат байты (октеты).
  • Кодировка преобразует строку Unicode в строку байтов.
  • Декодирование преобразует строку байтов в строку Unicode.

Строка, которую вы получаете от Amazon AWS, представляет собой строку байт . Вам нужно декодировать , чтобы получить строку Unicode. Но ваш фрагмент кода, encodeme = 'São Paulo', дает вам строку байтов. encodeme.encode('utf-8) выполняет кодирование () в байтовой строке, а это не то, что вам нужно. (Отсутствующая заключительная цитата на 'utf-8 не помогает.)

Попробуйте этот пример кода:

>>> reportbody = 'S\xc3\xa3o Paulo'   # UTF-8 encoded byte string
>>> reportbody.decode('utf-8')        # returns a Unicode string, u'...'
u'S\xe3o Paulo'

Возможно, вам пригодятся некоторые материалы для чтения. Я согласен с Hoxieboy, что вам стоит потратить время на чтение Python's Unicode HOWTO . Также ознакомьтесь с основными ответами на Что мне нужно знать о Unicode? .

1 голос
/ 30 января 2012

Официальная документация по Unicode Python

Вы можете попробовать эту веб-страницу, если вы еще этого не сделали, и посмотреть, сможете ли вы получить искомый ответ;)

...