2011-05-24 53 views
1

我无法让我的Python脚本通过RESTful http调用来识别Unicode数据。通过REST接口传递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.

接下来的想法是不使用卷曲,而只是尽一切在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()
+1

重复的非常多的帖子 - 看看http://stackoverflow.com/search?q=UnicodeEncodeError并选择你最喜欢的。 – bgporter 2011-05-24 15:26:45

+0

[Python Unicode UnicodeEncodeError]的可能重复(http://stackoverflow.com/questions/1077564/python-unicode-unicodeencodeerror) – bgporter 2011-05-24 15:28:10

回答

2

关于你的测试脚本,这是失败,因为要传递的Unicode对象urllib.urlencode()(它被称为为您urlopen())。它不支持unicode对象,因此它使用默认字符集(即ascii)进行隐式编码。显然,它失败了。

处理发布unicode对象最简单的方法是明确的;收集您的数据并构建一个字典,使用适当的字符集对unicode值进行编码,对字典进行urlencode(以获得可显示的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) 

编辑:更一般地,当你做出一个HTTP请求与Python(比如urllib2.urlopen), 的响应的内容是解码为Unicode为您服务。这意味着您需要了解发送它的服务器使用的编码。看看content-type标题;通常它包括一个charset=xyz

尽可能早地解码您的输入并尽可能晚地编码您的输出始终是明智之举。

相关问题