zoukankan      html  css  js  c++  java
  • 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:
    ', client.last_sent()
    print 'last recv:
    ', 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

    谢谢!

  • 相关阅读:
    ural(Timus) 1019 Line Painting
    ACMICPC Live Archive 2031 Dance Dance Revolution
    poj 3321 Apple Tree
    其他OJ 树型DP 选课
    poj 3548 Restoring the digits
    ACMICPC Live Archive 3031 Cable TV Network
    递归循环获取指定节点下面的所有子节点
    手动触发asp.net页面验证控件事件
    子级Repeater获取父级Repeater绑定项的值
    没有列名的数据绑定
  • 原文地址:https://www.cnblogs.com/Tommy-Yu/p/5567091.html
Copyright © 2011-2022 走看看