如何在Python中发送非ASCII POST请求?

7 投票
3 回答
6456 浏览
提问于 2025-04-17 09:46

我正在尝试向一个网页应用发送一个POST请求。我使用的是mechanize模块(它是urllib2的一个封装)。不过,当我尝试发送POST请求时,出现了一个错误:UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 0: ordinal not in range(128)。我试过用unicode(string)unicode(string, encoding="utf-8")unicode(string).encode()等等,但都没有用——要么返回上面的错误,要么出现TypeError: decoding Unicode is not supported的错误。

我查看了其他类似问题的回答,但都没有帮助。

提前谢谢大家!

编辑:产生错误的示例:

prda = "šđćč" #valid UTF-8 characters
prda # typing in python shell 
'\xc5\xa1\xc4\x91\xc4\x87\xc4\x8d'
print prda # in shell
šđćč
prda.encode("utf-8") #in shell
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 0: ordinal not in range(128)
unicode(prda)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 0: ordinal not in range(128)

3 个回答

0

你不需要把字符放在 unicode 调用里,因为它们已经被编码过了 :) 如果要做的话,你需要码才能得到一个unicode对象:

>>> s = '\xc5\xa1\xc4\x91\xc4\x87\xc4\x8d'   # your string
>>> s.decode('utf-8')
u'\u0161\u0111\u0107\u010d'
>>> type(s.decode('utf-8'))
<type 'unicode'>

我不太了解 mechanize,所以不太确定它是否处理得正确,抱歉。

如果是用普通的 urllib2 进行POST请求,我会使用 urlencode

>>> from urllib import urlencode
>>> postData = urlencode({'test': s })   # note I'm NOT decoding it
>>> postData
'test=%C5%A1%C4%91%C4%87%C4%8D'
>>> urllib2.urlopen(url, postData)   # etc etc etc
1

在你的例子中,你使用了一个包含非ASCII字符的非Unicode字符串,这导致prda变成了一个字节字符串。

为了实现这一点,Python会使用sys.stdin.encoding自动对字符串进行编码。在你的情况下,这意味着字符串会被编码为“utf-8”。

如果你想把prda转换成一个Unicode对象,你需要使用合适的编码进行解码:

>>> print prda.decode('utf-8')
šđćč

需要注意的是,在脚本或模块中,你不能指望Python自动猜测编码——你需要在文件顶部明确声明编码,像这样:

# -*- coding: utf-8 -*-

每当你在Python 2中遇到Unicode错误时,通常是因为你的代码混合了字节字符串和Unicode字符串。所以你应该总是检查是什么类型的字符串导致了错误,可以使用type(string)来查看。

如果字符串对象是<type 'str'>,但你需要的是Unicode,那就用合适的编码进行解码。如果字符串对象是<type 'unicode'>,但你需要的是字节,那就用合适的编码进行编码

9

我猜你是在用Python 2.x版本。

假设你有一个unicode对象:

myUnicode = u'\u4f60\u597d'

你可以用utf-8格式来编码它:

mystr = myUnicode.encode('utf-8')

注意,你需要明确指定编码方式。默认情况下,它通常会使用ascii编码。

撰写回答