當被調用服務的返回xml內容值不是按照wsdl文件描述定義的, 就莫名奇妙返回suds.WebFault
沒有更多詳細信息!
於是將源碼解壓,並插入到sys.path[0], 通過設置斷點的方式找出非標准的返回報文到底在說啥。從而調整對應參數。
suds-0.4/suds/bindings/binding.py (246~268)
def get_fault(self, reply): """ Extract the fault from the specified soap reply. If I{faults} is True, an exception is raised. Otherwise, the I{unmarshalled} fault L{Object} is returned. This method is called when the server raises a I{web fault}. @param reply: A soap reply message. @type reply: str @return: A fault object. @rtype: tuple ( L{Element}, L{Object} ) """ import pdb pdb.set_trace() reply = self.replyfilter(reply) sax = Parser() faultroot = sax.parse(string=reply) soapenv = faultroot.getChild('Envelope') soapbody = soapenv.getChild('Body') fault = soapbody.getChild('Fault') unmarshaller = self.unmarshaller(False) p = unmarshaller.process(fault) if self.options().faults: raise WebFault(p, faultroot) return (faultroot, p.detail)
順便記錄下suds神器的基本用法,方便查閱:
1. 查看服務接口
import suds client=suds.client.Client('xxxx_webservice_url') def get_all_methods(client): return [method for method in client.wsdl.services[0].ports[0].methods]
2. 查看某個具體接口的傳輸參數及類型
def get_method_args(client, method_name): method = client.wsdl.services[0].ports[0].methods[method_name] input_params = method.binding.input return input_params.param_defs(method)
3. 調用接口服務
client.service.xxx_function(....)
4. 關於調試
輸出之前調用服務接口時發送了什么soap報文,以及收到什么樣的soap報文
print 'last sent:\n', client.last_sent() print 'last recv:\n', client.last_received()
當服務器返回報文格式不規范時(非wsdl中定義的),client.last_received()為None。這個時候顯然對聯調極為不利。
那就利用suds自身的日志記錄看看咯。設定如下:
import sys
import logging logger = logging.getLogger('suds') logger.setLevel(logging.DEBUG) logger.addHandler(logging.StreamHandler(sys.stdout))
如果只關心傳輸了什么,則可以限定logger為“suds.transport.http“
import sys logger = logging.getLogger('suds.transport.http') logger.setLevel(logging.DEBUG) logger.addHandler(logging.StreamHandler(sys.stdout))
5. 異常的捕捉和輸出
try: client.service.xxx_func(*args, **kwargs) except suds.WebFault,ex: print ex.fault print ex.document
后記:對於第三方庫莫名其妙的問題,果斷及時拿源碼過來剖析(至少debug)
DEMO
來個demo說明如何運用,如下:
>>> import suds >>> url='http://www.gpsso.com/webservice/kuaidi/kuaidi.asmx?wsdl' >>> client = suds.client.Client(url) >>> print get_all_methods(client) [KuaidiQuery] >>> print get_method_args(client, 'KuaidiQuery') [(Compay, <Element:0x7f6c55bc43d0 name="Compay" type="(u'string', u'http://www.w3.org/2001/XMLSchema')" />), (OrderNo, <Element:0x7f6c55bc4450 name="OrderNo" type="(u'string', u'http://www.w3.org/2001/XMLSchema')" />)] >>> print client.service.KuaidiQuery(Company='EMS', OrderNo='1111') (KuaidiQueryResult){ API = (API){ RESULTS = "0" MESSAGE = "接口查詢成功" } } >>> print client.last_sent() <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://gpsso.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <ns0:Body> <ns1:KuaidiQuery> <ns1:OrderNo>1111</ns1:OrderNo> </ns1:KuaidiQuery> </ns0:Body> </SOAP-ENV:Envelope> >>> print client.last_received() <?xml version="1.0" encoding="UTF-8"?> <soap:Envelope> <soap:Body> <KuaidiQueryResponse xmlns="http://gpsso.com/"> <KuaidiQueryResult> <API> <RESULTS>0</RESULTS> <MESSAGE>接口查詢成功</MESSAGE> </API> </KuaidiQueryResult> </KuaidiQueryResponse> </soap:Body> </soap:Envelope>
轉載請注明本文來源:http://www.cnblogs.com/Tommy-Yu/p/5567091.html
謝謝!