base64编码python 2.7中的unicode字符串

时间:2012-03-05 18:57:23

标签: python character-encoding base64 unicode-string python-unicode

我有一个使用requests module从web服务检索到的unicode字符串,包含二进制文档的字节(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:\Python27\Lib\base64.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:\Python27\Lib\base64.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 个答案:

答案 0 :(得分:18)

您有一个unicode字符串,您想要base64编码。问题是b64encode()仅适用于字节,而不适用于字符。因此,您需要将unicode字符串(这是一系列抽象的Unicode代码点)转换为字节字符串。

将抽象Unicode字符串映射到具体的字节序列称为 encoding 。 Python支持多种编码;我建议广泛使用的UTF-8编码:

byte_string = response_dict['content'].encode('utf-8')

请注意,无论是谁解码字节,还需要知道使用哪种编码通过补充unicode函数获取decode()字符串:

# Decode
decoded = byte_string.decode('utf-8')

了解有关Unicode和编码的更多信息的良好起点是Joel Spolsky的Python docsthis article

答案 1 :(得分:5)

我建议首先在base64编码之前将其编码为UTF-8:

In [12]: my_unicode = u'\xf8'

In [13]: my_utf8 = my_unicode.encode('utf-8')

In [15]: base64.b64encode(my_utf8)
Out[15]: 'w7g='

答案 2 :(得分:2)

由于您正在使用二进制数据,我不确定使用utf-8编码是个好主意。我想这取决于你打算如何使用base64编码表示。我认为如果您可以将数据检索为字节字符串而不是unicode字符串可能会更好。我从未使用过请求库,但浏览文档表明它是可能的。有部分讨论“二进制响应内容”和“原始响应内容”。

答案 3 :(得分:1)

应该可以将响应作为二进制字节获取并完全跳过解码和编码步骤。 requests总是有可能选择在往返过程中丢失一些数据或错误的编码。

这部分名为"Binary Response Content"的文档似乎完全适合您的问题。

答案 4 :(得分:0)

如果它是二进制数据......为什么要进行编码/解码?特别是&#34; base64.encodestring&#34;部分。下面是我如何将图像编码到base64中直接添加到我的python代码而不是有额外的文件。 2.7.2 btw

import base64
iconfile = open("blah.icon","rb")
icondata = iconfile.read()
icondata = base64.b64encode(icondata)