base64 кодирование строк unicode в python 2.7
у меня есть строка unicode, полученная из веб-службы с помощью requests
модуль, который содержит байты двоичного документа (PCL, как это бывает). Один из этих байтов имеет значение 248, и попытка кодирования base64 приводит к следующей ошибке:
In [68]: base64.b64encode(response_dict['content']+'n')
---------------------------------------------------------------------------
UnicodeEncodeError Traceback (most recent call last)
C:...<ipython-input-68-8c1f1913eb52> in <module>()
----> 1 base64.b64encode(response_dict['content']+'n')
C:Python27Libbase64.pyc in b64encode(s, altchars)
51 """
52 # Strip off the trailing newline
---> 53 encoded = binascii.b2a_base64(s)[:-1]
54 if altchars is not None:
55 return _translate(encoded, {'+': altchars[0], '/': altchars[1]})
UnicodeEncodeError: 'ascii' codec can't encode character u'xf8' in position 272: ordinal not in range(128)
In [69]: response_dict['content'].encode('base64')
---------------------------------------------------------------------------
UnicodeEncodeError Traceback (most recent call last)
C:...<ipython-input-69-7fd349f35f04> in <module>()
----> 1 response_dict['content'].encode('base64')
C:...base64_codec.pyc in base64_encode(input, errors)
22 """
23 assert errors == 'strict'
---> 24 output = base64.encodestring(input)
25 return (output, len(input))
26
C:Python27Libbase64.pyc in encodestring(s)
313 for i in range(0, len(s), MAXBINSIZE):
314 chunk = s[i : i + MAXBINSIZE]
--> 315 pieces.append(binascii.b2a_base64(chunk))
316 return "".join(pieces)
317
UnicodeEncodeError: 'ascii' codec can't encode character u'xf8' in position 44: ordinal not in range(128)
Я нахожу это немного удивительным, потому что 248 находится в диапазоне беззнакового байта (и может храниться в строке байта), но мой реальный вопрос: что лучше или правильно кодировать эту строку?
моя текущая работа вокруг этого:
In [74]: byte_string = ''.join(map(compose(chr, ord), response_dict['content']))
In [75]: byte_string[272]
Out[75]: 'xf8'
это, кажется, работает правильно, и в результате byte_string
способен быть закодированным base64, но, похоже, должен быть лучший способ. Есть?
5 ответов
поскольку вы работаете с двоичными данными, я не уверен, что это хорошая идея использовать кодировку utf-8. Я думаю, это зависит от того, как вы собираетесь использовать base64 закодированные представления. Я думаю, было бы лучше, если бы вы могли получить данные в виде строки байтов, а не строки unicode. Я никогда не использовал библиотеку запросов, но просмотр документации предполагает, что это возможно. Есть разделы, говорящие о "двоичном содержании ответа"и" необработанном содержании ответа".
у вас unicode
строка, которую вы хотите кодировать base64. Проблема в том, что b64encode()
работает только на байт, а не символы. Итак, вам нужно преобразовать свой unicode
string (которая представляет собой последовательность абстрактных кодовых точек Unicode) в байтовую строку.
отображение абстрактных строк Unicode в конкретный ряд байтов называется кодирование. Python поддерживает несколько кодировок; я предлагаю широко используемый UTF-8 кодировка:
byte_string = response_dict['content'].encode('utf-8')
обратите внимание, что тот, кто декодирует байты, также должен знать, какая кодировка использовалась для возврата unicode
строка через комплементарную decode()
функция:
# Decode
decoded = byte_string.decode('utf-8')
хорошей отправной точкой для получения дополнительной информации о Unicode и кодировках является Python docs и в этой статье Джоэл Спольски.
Я бы предложил сначала кодировать его на что-то вроде UTF-8 перед кодировкой base64:
In [12]: my_unicode = u'\xf8'
In [13]: my_utf8 = my_unicode.encode('utf-8')
In [15]: base64.b64encode(my_utf8)
Out[15]: 'w7g='
должно быть возможно получить ответ в виде двоичных байтов и полностью пропустить шаги декодирования и кодирования. Всегда есть вероятность, что requests
выберет кодировку, которая теряет некоторые данные или ошибки в поездке туда и обратно.
эта часть документов называется "Содержание Двоичного Ответа" кажется, идеально подходит для вашей проблемы.
Если это двоичные данные...зачем вообще кодировать / декодировать? Особенно "в base64.encodestring" часть. Ниже показано, как я кодирую изображения в base64 для добавления непосредственно в мой код python вместо дополнительных файлов. 2.7.2 btw
import base64
iconfile = open("blah.icon","rb")
icondata = iconfile.read()
icondata = base64.b64encode(icondata)