Python: "...".encode("utf8") 修复了什么?

9 投票
6 回答
9937 浏览
提问于 2025-04-16 01:34

我想把一个Python字符串进行URL编码,但在处理希伯来语字符串时遇到了错误。我没能解决这个问题,只好开始尝试各种方法。最后,在把字符串发送给URL编码器之前,先用mystr = mystr.encode("utf8")处理了一下,问题就解决了。

有人能解释一下发生了什么吗?这个.encode("utf8")到底是干嘛的?反正我原来的字符串就是一个unicode字符串(也就是前面有个u的那种)。

6 个回答

4

.encode("utf8") 是干什么的?

这要看你用的是哪个版本的Python:

  • 在Python 3.x中,它把一个 str 对象(用UTF-16或UTF-32编码的)转换成一个 bytes 对象,这个对象里面是字符串的UTF-8表示。
  • 在Python 2.x中,它把一个 unicode 对象转换成一个用UTF-8编码的 str 对象。不过 str 也有一个 encode 方法,所以写 '...'.encode('UTF-8') 和写 '...'.decode('ascii').encode('UTF-8') 是一样的。

因为你提到了“u”前缀,所以你一定是在用2.x。如果你不需要任何只在2.x中用的库,我建议你换到3.x,因为它在文本和二进制数据之间有很清晰的区分。

深入了解Python 3 对这个问题有很好的解释。

有人能解释发生了什么吗?

如果你告诉我们错误信息是什么,会更有帮助。

urllib.quote 函数需要一个 str 对象。它也可以处理只包含ASCII字符的 unicode 对象,但如果里面有希伯来字母就不行了。

在Python 3.x中,urllib.parse.quote 可以接受 str(相当于Python 2.x的 unicode)和 bytes 对象。字符串会自动用UTF-8编码。

13

我最开始的字符串本来就是一个unicode字符串(也就是前面有个u的那种)

...这就是问题所在。它并不是一个普通的“字符串”,而是一个“Unicode对象”。这个对象里面包含了一串Unicode编码点。这些编码点在内部有Python能理解的表示方式,但具体是什么就不重要了。当你用 print repr(my_u_str) 打印出来时,它们会显示成 \uXXXX 这样的形式。

如果你想得到其他程序能理解的字节序列,你需要把这串Unicode编码点进行编码。你需要选择一种编码方式,因为有很多种可以选择。常见的有UTF8和UTF16。如果内容适合的话,ASCII也可以用。比如 u"abc".encode('ascii') 就可以正常工作。

你可以试试 my_u_str = u"\u2119ython" 然后用 type(my_u_str)type(my_u_str.encode('utf8')) 来看看类型的区别:第一个是 <type 'unicode'>,而第二个是 <type 'str'>。(在Python 2.5和2.6下是这样的)

在Python 3中情况有所不同,但因为我很少用它,所以如果我说什么权威的东西可能就不太靠谱了。

9

你最开始的字符串是一个包含原始Unicode编码点的Unicode对象,经过UTF-8编码后,它变成了一个普通的字节字符串,这里面包含的是UTF-8编码的数据。

URL编码器似乎是期待一个字节字符串,这样它就可以一个字节一个字节地进行URL编码,而不需要处理Unicode编码点。当你给它一个Unicode对象时,它会尝试用某种默认编码(可能是ASCII)把它转换成字节字符串。对于那些不能用ASCII表示的希伯来字符,这样就会出现错误。

撰写回答