python suds 一坑

当被调用服务的返回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='')
(KuaidiQueryResult){
API =
(API){
RESULTS = ""
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

谢谢!

上一篇:Cracking The Coding Interview 5.5


下一篇:HttpClient——连接关闭