環境:Python的2.7.4(部分在Windows上,部分在Linux上,見下文),泡沫(含有少量的修改SVN HEAD)嵌套文本編碼請求
我需要調用,需要一個Web服務一個參數,它是一個XML字符串(是的,我知道...),即請求與以下類型的WSDL聲明:
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="actionString" type="s:string"/>
</s:sequence>
</s:complexType>
我使用cElementTree
構建這種內在的XML文檔,然後我將它作爲泡沫產生的client.service.ProcessAction(request)
方法的唯一參數傳遞給它。
有一段時間,這個效果不錯:
root = ET.Element(u'ActionCommand')
value = ET.SubElement(root, u'value')
value.text = saxutils.escape(complex_value)
request = u'<?xml version="1.0" encoding="utf-8"?>\n' + ET.tostring(root, encoding='utf-8')
client.service.ProcessAction(request)
的saxutils.escape
,我在某些時候又增加了固定第一編碼的問題,幾乎沒有能夠明白到底爲什麼我需要它,有什麼區別它使。
現在(可能是由於英鎊符號第一次出現的),我突然得到了以下異常:
Traceback (most recent call last):
File "/app/module.py", line 135, in _process_web_service_call
request = u'<?xml version="1.0" encoding="utf-8"?>\n' + ET.tostring(root, encoding='utf-8')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 137: ordinal not in range(128)
這裏的137位對應於內部XML請求中的特殊字符的位置。顯然,即使給出編碼,cElementTree.tostring()也會返回'str'類型,而不是'unicode'。所以Python試圖將這個字符串str解碼爲unicode(爲什麼用'ascii'?),以便它可以將它與unicode文字連接起來。這失敗了(當然,因爲str實際上是用UTF-8編碼的,而不是ASCII編碼)。
所以我想,好,我會對其進行解碼爲Unicode自己則:,它吹起來的泡沫裏面,它試圖爲某些原因解碼外XML請求
root = ET.Element(u'ActionCommand')
value = ET.SubElement(root, u'value')
value.text = saxutils.escape(complex_value)
request_encoded_str = ET.tostring(root, encoding='utf-8')
request_unicode = request_encoded_str.decode('utf-8')
request = u'<?xml version="1.0" encoding="utf-8"?>\n' + request_unicode
client.service.ProcessClientAction(request)
只是現在:
Traceback (most recent call last):
File "/app/module.py", line 141, in _process_web_service_call
raw_response = client.service.ProcessAction(request)
File "/app/.heroku/python/lib/python2.7/site-packages/suds/client.py", line 542, in __call__
return client.invoke(args, kwargs)
File "/app/.heroku/python/lib/python2.7/site-packages/suds/client.py", line 602, in invoke
result = self.send(soapenv)
File "/app/.heroku/python/lib/python2.7/site-packages/suds/client.py", line 643, in send
reply = transport.send(request)
File "/app/.heroku/python/lib/python2.7/site-packages/suds/transport/https.py", line 64, in send
return HttpTransport.send(self, request)
File "/app/.heroku/python/lib/python2.7/site-packages/suds/transport/http.py", line 118, in send
return self.invoke(request)
File "/app/.heroku/python/lib/python2.7/site-packages/suds/transport/http.py", line 153, in invoke
u2response = urlopener.open(u2request, timeout=tm)
File "/app/.heroku/python/lib/python2.7/urllib2.py", line 404, in open
response = self._open(req, data)
File "/app/.heroku/python/lib/python2.7/urllib2.py", line 422, in _open
'_open', req)
File "/app/.heroku/python/lib/python2.7/urllib2.py", line 382, in _call_chain
result = func(*args)
File "/app/.heroku/python/lib/python2.7/urllib2.py", line 1222, in https_open
return self.do_open(httplib.HTTPSConnection, req)
File "/app/.heroku/python/lib/python2.7/urllib2.py", line 1181, in do_open
h.request(req.get_method(), req.get_selector(), req.data, headers)
File "/app/.heroku/python/lib/python2.7/httplib.py", line 973, in request
self._send_request(method, url, body, headers)
File "/app/.heroku/python/lib/python2.7/httplib.py", line 1007, in _send_request
self.endheaders(body)
File "/app/.heroku/python/lib/python2.7/httplib.py", line 969, in endheaders
self._send_output(message_body)
File "/app/.heroku/python/lib/python2.7/httplib.py", line 827, in _send_output
msg += message_body
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 565: ordinal not in range(128)
此處的位置565再次與上述相同,除了這次是我的內部XML請求的位置嵌入由泡沫創建的外部XML請求(SOAP)中。
我很困惑。任何人都可以幫我解決這個問題嗎? :)
更糟的是,所有這些只發生在Linux下的服務器上。這些都不會在Windows上的開發環境中引發異常。 (關於爲什麼這樣說的附加說明,僅僅是因爲我很好奇,我懷疑它與不同的默認編碼有關。)但是,它們都不被服務器接受。如果我放棄saxutils.escape
,然後將適當的unicode對象粘貼到泡沫上,Windows上的工作是什麼。但是,這仍然導致Linux上的相同UnicodeDecodeError
。
更新:我開始在Windows(其中正常工作)調試這一點,並在該行httplib.py的827,它的確試圖以連接unicode的對象msg
(包含HTTP頭)和STR對象message_body
,導致使用不正確編碼的隱式unicode解碼。我想這只是因爲某些原因在Windows上不會失敗。我不明白爲什麼suds試圖發送一個str對象時,我把一個unicode對象放在頂部。