130

我想在 Python 中使用基于 WSDL SOAP 的 Web 服务。我查看了Dive Into Python代码,但 SOAPpy 模块在 Python 2.5 下不起作用。

我曾尝试使用部分有效的suds,但会与某些类型中断(suds.TypeNotFound:找不到类型:'item')。

我也看过Client但这似乎不支持 WSDL。

我看过ZSI,但它看起来非常复杂。有没有人有任何示例代码?

WSDL 是https://ws.pingdom.com/soap/PingdomAPI.wsdl并且可以与 PHP 5 SOAP 客户端一起正常工作。

4

10 回答 10

49

我建议你看看SUDS

“Suds 是一个用于使用 Web 服务的轻量级 SOAP python 客户端。”

于 2010-05-13T19:02:39.243 回答
31

有一个相对较新的库,它非常有前途,尽管文档仍然很差,但看起来非常干净和 pythonic:python zeep

另请参阅此答案以获取示例。

于 2016-04-28T09:33:04.593 回答
19

我最近偶然发现了同样的问题。这是我的解决方案的概要:

需要的基本组成代码块

以下是您的客户端应用程序所需的基本代码块

  1. 会话请求部分:请求与提供者的会话
  2. 会话身份验证部分:向提供者提供凭据
  3. 客户端部分:创建客户端
  4. 安全标头部分:将 WS-Security 标头添加到客户端
  5. 消费部分:根据需要消费可用的操作(或方法)

你需要什么模块?

许多人建议使用 Python 模块,例如 urllib2 ;然而,没有一个模块可以工作——至少对于这个特定的项目是这样。

因此,这是您需要获取的模块列表。首先,您需要从以下链接下载并安装最新版本的 suds:

pypi.python.org/pypi/suds-jurko/0.4.1.jurko.2

此外,您需要分别从以下链接下载和安装 requests 和 suds_requests 模块(免责声明:我是新来这里发布的,所以我现在不能发布多个链接)。

pypi.python.org/pypi/requests

pypi.python.org/pypi/suds_requests/0.1

成功下载并安装这些模块后,您就可以开始使用了。

编码

按照前面概述的步骤,代码如下所示: 导入:

import logging
from suds.client import Client
from suds.wsse import *
from datetime import timedelta,date,datetime,tzinfo
import requests
from requests.auth import HTTPBasicAuth
import suds_requests

会话请求和身份验证:

username=input('Username:')
password=input('password:')
session = requests.session()
session.auth=(username, password)

创建客户端:

client = Client(WSDL_URL, faults=False, cachingpolicy=1, location=WSDL_URL, transport=suds_requests.RequestsTransport(session))

添加 WS-Security 标头:

...
addSecurityHeader(client,username,password)
....

def addSecurityHeader(client,username,password):
    security=Security()
    userNameToken=UsernameToken(username,password)
    timeStampToken=Timestamp(validity=600)
    security.tokens.append(userNameToken)
    security.tokens.append(timeStampToken)
    client.set_options(wsse=security)

请注意,此方法创建图 1 中描述的安全标头。因此,您的实现可能会有所不同,具体取决于您正在使用的服务的所有者提供的正确安全标头格式。

消费相关方法(或操作):

result=client.service.methodName(Inputs)

记录

此类实现中的最佳实践之一是记录以查看通信是如何执行的。万一出现问题,它使调试变得容易。以下代码执行基本日志记录。但是,除了代码中描述的内容之外,您还可以记录通信的许多方面。

logging.basicConfig(level=logging.INFO) 
logging.getLogger('suds.client').setLevel(logging.DEBUG) 
logging.getLogger('suds.transport').setLevel(logging.DEBUG)

结果:

这是我的情况的结果。请注意,服务器返回 HTTP 200。这是 HTTP 请求响应的标准成功代码。

(200, (collectionNodeLmp){
   timestamp = 2014-12-03 00:00:00-05:00
   nodeLmp[] = 
      (nodeLmp){
         pnodeId = 35010357
         name = "YADKIN"
         mccValue = -0.19
         mlcValue = -0.13
         price = 36.46
         type = "500 KV"
         timestamp = 2014-12-03 01:00:00-05:00
         errorCodeId = 0
      },
      (nodeLmp){
         pnodeId = 33138769
         name = "ZION 1"
         mccValue = -0.18
         mlcValue = -1.86
         price = 34.75
         type = "Aggregate"
         timestamp = 2014-12-03 01:00:00-05:00
         errorCodeId = 0
      },
 })
于 2014-12-04T19:13:20.773 回答
10

Zeep 是一个不错的 Python SOAP 库,符合您的要求:http ://docs.python-zeep.org

于 2017-04-22T18:56:26.160 回答
7

Right now (as of 2008), all the SOAP libraries available for Python suck. I recommend avoiding SOAP if possible. The last time we where forced to use a SOAP web service from Python, we wrote a wrapper in C# that handled the SOAP on one side and spoke COM out the other.

于 2008-09-22T15:55:07.233 回答
6

我会定期为此寻找令人满意的答案,但到目前为止还没有运气。我使用soapUI +请求+体力劳动。

上次我需要这样做时我放弃并使用了 Java ,并且在我最后一次要这样做时简单地放弃了几次,但这并不是必需的。

去年通过 Project Place 的 RESTful API 成功使用 requests 库后,我突然想到,也许我可以手动滚动我想以类似方式发送的 SOAP 请求。

事实证明这并不太难,但它既费时又容易出错,尤其是如果字段名称不一致(我今天正在处理的有'jobId',JobId'和'JobID'。我使用soapUI加载WSDL,以便更容易提取端点等并执行一些手动测试。到目前为止,我很幸运没有受到我正在使用的任何 WSDL 更改的影响。

于 2013-11-07T11:54:38.630 回答
3

这不是真的 SOAPpy 不适用于 Python 2.5 - 它可以工作,尽管它非常简单并且非常非常基本。如果您想与任何更复杂的 Web 服务交谈,ZSI 是您唯一的朋友。

我发现的真正有用的演示位于http://www.ebi.ac.uk/Tools/webservices/tutorials/python - 这确实帮助我理解了 ZSI 的工作原理。

于 2008-09-22T19:38:22.360 回答
1

SOAPpy 现在已经过时了,AFAIK 被 ZSL 取代。这是一个有争议的问题,因为我无法在 Python 2.5 或 Python 2.6 上让任何一个工作,更不用说编译了

于 2010-04-02T16:33:07.007 回答
1

如果您自己动手,我强烈建议您查看http://effbot.org/zone/element-soap.htm

于 2010-01-19T11:13:16.103 回答
1
#!/usr/bin/python
# -*- coding: utf-8 -*-
# consume_wsdl_soap_ws_pss.py
import logging.config
from pysimplesoap.client import SoapClient

logging.config.dictConfig({
    'version': 1,
    'formatters': {
        'verbose': {
            'format': '%(name)s: %(message)s'
        }
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
        },
    },
    'loggers': {
        'pysimplesoap.helpers': {
            'level': 'DEBUG',
            'propagate': True,
            'handlers': ['console'],
        },
    }
})

WSDL_URL = 'http://www.webservicex.net/stockquote.asmx?WSDL'
client = SoapClient(wsdl=WSDL_URL, ns="web", trace=True)
client['AuthHeaderElement'] = {'username': 'someone', 'password': 'nottelling'}

#Discover operations
list_of_services = [service for service in client.services]
print(list_of_services)

#Discover params
method = client.services['StockQuote']

response = client.GetQuote(symbol='GOOG')
print('GetQuote: {}'.format(response['GetQuoteResult']))
于 2017-03-23T16:06:36.997 回答