如何在Python中发送非ASCII POST请求?
我正在尝试向一个网页应用发送一个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 个回答
你不需要把字符放在 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
在你的例子中,你使用了一个包含非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'>
,但你需要的是字节,那就用合适的编码进行编码。
我猜你是在用Python 2.x版本。
假设你有一个unicode对象:
myUnicode = u'\u4f60\u597d'
你可以用utf-8格式来编码它:
mystr = myUnicode.encode('utf-8')
注意,你需要明确指定编码方式。默认情况下,它通常会使用ascii编码。