SUDS - 编程访问方法和类型

23 投票
8 回答
30312 浏览
提问于 2025-04-11 09:35

我正在研究SUDS这个工具,它可以作为Python的SOAP客户端。我想查看一个特定服务提供的方法,以及某个方法需要的参数类型。

我的目标是生成一个用户界面,让用户可以选择一个方法,然后在动态生成的表单中填写相应的值。

我可以获取某个特定方法的一些信息,但不太确定如何解析这些信息:

client = Client(url)
method = client.sd.service.methods['MyMethod']

我无法通过编程的方式弄清楚我需要创建什么样的对象类型,才能调用这个服务。

obj = client.factory.create('?')

res = client.service.MyMethod(obj, soapheaders=authen)

有没有人能提供一些示例代码?

8 个回答

10

这里有一个我根据上面的信息写的简单脚本,用来列出在WSDL上可用的输入方法suds报告。只需要输入WSDL的链接就可以了。这个脚本在我现在的项目中能用,但我不能保证在你的项目中也能用。

import suds

def list_all(url):
    client = suds.client.Client(url)
    for service in client.wsdl.services:
        for port in service.ports:
            methods = port.methods.values()
            for method in methods:
                print(method.name)
                for part in method.soap.input.body.parts:
                    part_type = part.type
                    if(not part_type):
                        part_type = part.element[0]
                    print('  ' + str(part.name) + ': ' + str(part_type))
                    o = client.factory.create(part_type)
                    print('    ' + str(o))
20

根据 suds文档,你可以用 __str()__ 来查看 service 对象的内容。这样,你就可以得到一个方法和复杂类型的列表:

from suds.client import Client;

url = 'http://www.webservicex.net/WeatherForecast.asmx?WSDL'
client = Client(url)

temp = str(client);

上面的代码会产生以下结果(temp 的内容):

Suds ( https://fedorahosted.org/suds/ )  version: 0.3.4 (beta)  build: R418-20081208

Service ( WeatherForecast ) tns="http://www.webservicex.net"
   Prefixes (1)
      ns0 = "http://www.webservicex.net"
   Ports (2):
      (WeatherForecastSoap)
         Methods (2):
            GetWeatherByPlaceName(xs:string PlaceName, )
            GetWeatherByZipCode(xs:string ZipCode, )
         Types (3):
            ArrayOfWeatherData
            WeatherData
            WeatherForecasts
      (WeatherForecastSoap12)
         Methods (2):
            GetWeatherByPlaceName(xs:string PlaceName, )
            GetWeatherByZipCode(xs:string ZipCode, )
         Types (3):
            ArrayOfWeatherData
            WeatherData
            WeatherForecasts

这样会更容易理解。而且每个方法都会列出它的参数和类型。你甚至可以用普通的正则表达式来提取你需要的信息。

30

好的,SUDS 这个工具真的是很神奇。

一个 suds.client.Client 是通过一个 WSDL 文件来创建的:

client = suds.client.Client("http://mssoapinterop.org/asmx/simple.asmx?WSDL")

它会下载这个 WSDL 文件,并在 client.wsdl 中创建一个定义。当你通过 client.service.<method> 调用某个方法时,其实在背后有很多复杂的处理在进行,都是在对这个解析后的 WSDL 文件进行操作。要想了解方法的参数和类型,你需要查看这个对象的内部结构。

举个例子:

for method in client.wsdl.services[0].ports[0].methods.values():
    print '%s(%s)' % (method.name, ', '.join('%s: %s' % (part.type, part.name) for part in method.soap.input.body.parts))

这应该会打印出类似这样的内容:

echoInteger((u'int', http://www.w3.org/2001/XMLSchema): inputInteger)
echoFloatArray((u'ArrayOfFloat', http://soapinterop.org/): inputFloatArray)
echoVoid()
echoDecimal((u'decimal', http://www.w3.org/2001/XMLSchema): inputDecimal)
echoStructArray((u'ArrayOfSOAPStruct', http://soapinterop.org/xsd): inputStructArray)
echoIntegerArray((u'ArrayOfInt', http://soapinterop.org/): inputIntegerArray)
echoBase64((u'base64Binary', http://www.w3.org/2001/XMLSchema): inputBase64)
echoHexBinary((u'hexBinary', http://www.w3.org/2001/XMLSchema): inputHexBinary)
echoBoolean((u'boolean', http://www.w3.org/2001/XMLSchema): inputBoolean)
echoStringArray((u'ArrayOfString', http://soapinterop.org/): inputStringArray)
echoStruct((u'SOAPStruct', http://soapinterop.org/xsd): inputStruct)
echoDate((u'dateTime', http://www.w3.org/2001/XMLSchema): inputDate)
echoFloat((u'float', http://www.w3.org/2001/XMLSchema): inputFloat)
echoString((u'string', http://www.w3.org/2001/XMLSchema): inputString)

所以,部分类型元组的第一个元素可能就是你想要的:

>>> client.factory.create(u'ArrayOfInt')
(ArrayOfInt){
   _arrayType = ""
   _offset = ""
   _id = ""
   _href = ""
   _arrayType = ""
 }

更新:

对于天气服务来说,似乎“参数”是一个带有 element 的部分,而不是 type

>>> client = suds.client.Client('http://www.webservicex.net/WeatherForecast.asmx?WSDL')
>>> client.wsdl.services[0].ports[0].methods.values()[0].soap.input.body.parts[0].element
(u'GetWeatherByZipCode', http://www.webservicex.net)
>>> client.factory.create(u'GetWeatherByZipCode')
(GetWeatherByZipCode){
   ZipCode = None
 }

但这些都被巧妙地转化为方法调用的参数(比如 client.service.GetWeatherByZipCode("12345"))。如果我没记错的话,这种方式是 SOAP RPC 绑定风格?我觉得这里的信息足够让你入门了。提示:Python 的命令行界面会是你的好帮手!

撰写回答