我无法让我的Python脚本通过RESTful http调用来识别Unicode数据。
我有一个脚本,使用REST接口从网站X读取数据,然后使用它的REST接口将其推送到网站Y.两个系统都是开源的,并在我们的服务器上运行。 Site X使用PHP,Apache和PostgreSQL。站点Y是Java,Tomcat和PostgreSQL。执行处理的脚本目前在Python中。
通常,脚本运行良好。我们确实有一些国际用户,在尝试处理名字中包含unicode字符的用户时,事情会发生故障。脚本的原始版本将JSON数据读入Python。数据自动转换为Unicode。我很确定到目前为止一切正常。为了输出数据,我使用subprocess.Popen()来调用curl。这适用于常规的ascii,但unicode在运输过程中的某个地方被破坏了。我没有在任何地方收到错误,但在网站B上查看结果时,它不再正确编码。
我知道这些字段支持Unicode,因为我可以使用Firefox正确地将数据添加到站点B来创建请求。
接下来的想法是不使用curl,而只是用Python做一切。我通过将一个手构造的Unicode字符串传递给Python的urllib来进行实验,以进行REST调用,但是我收到了来自urllib.urlopen()的错误:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 103-105: ordinal not in range(128)
有关如何使这项工作的任何想法?我宁愿不重写太多,但如果有另一种更适合的脚本语言,我也不介意听到这个。
这是我的Python测试脚本:
import urllib uni = u"abc_\u03a0\u03a3\u03a9" post = u"xdat%3Auser.login=unitest&" post += u"xdat%3Auser.primary_password=nauihe4r93nf83jshhd83&" post += u"xdat%3Auser.firstname=" + uni + "&" post += u"xdat%3Auser.lastname=" + uni ; url = u"http://localhost:8081/xnat/app/action/XDATRegisterUser" data = urllib.urlopen(url,post).read()
答案 0 :(得分:2)
关于您的测试脚本,它失败了,因为您正在将unicode对象传递给urllib.urlencode()
(urlopen()
正在为您调用它)。它不支持unicode对象,因此它使用默认字符集隐式编码,即ascii
。显然,它失败了。
处理POST unicode对象的最简单方法是显式;收集数据并构建一个dict,使用适当的字符集对unicode值进行编码,对dict进行urlencode(获取POSTable ascii字符串),然后启动请求。您的示例可以重写为:
import urllib
import urllib2
## Build our post data dict
data = {
'xdat:user.login' : u'unitest',
'xdat:primary_password' : u'nauihe4r93nf83jshhd83',
'xdat:firstname' : u"abc_\u03a0\u03a3\u03a9",
'xdat:lastname' : u"abc_\u03a0\u03a3\u03a9",
}
## Encode the unicode using an appropriate charset
data = dict([(key, value.encode('utf8')) for key, value in data.iteritems()])
## Urlencode it for POSTing
data = urllib.urlencode(data)
## Build a POST request, get the response
url = "http://localhost:8081/xnat/app/action/XDATRegisterUser"
request = urllib2.Request(url, data)
response = urllib2.urlopen(request)
编辑:更一般地说,当您使用python发出http请求时(比如urllib2.urlopen
),
响应的内容不为您解码为unicode。这意味着您需要了解发送它的服务器所使用的编码。查看content-type
标题;通常它包含charset=xyz
。
尽可能早地解码您的输入,并尽可能晚地对输出进行编码。