Как я могу использовать веб-сервис WSDL (SOAP) в Python?

Я хочу использовать веб-сервис на основе WSDL SOAP в Python. Я посмотрел код Dive Into Python, но модуль SOAPpy не работает в Python 2.5.

Я попытался использовать suds, который работает частично, но не работает с определенными типами (suds.TypeNotFound: Тип не найден: 'item').

Я также посмотрел на клиента, но это не поддерживает WSDL.

И я посмотрел на ZSI, но это выглядит очень сложно. У кого-нибудь есть пример кода для него?

WSDL - https://ws.pingdom.com/soap/PingdomAPI.wsdl и отлично работает с клиентом PHP 5 SOAP.

11 ответов

Решение

Я знаю, что это старый поток, но он показывал в верхней части результатов Google, поэтому я хотел бы поделиться более актуальным обсуждением Python и SOAP.

Смотрите: http://www.diveintopython.net/soap_web_services/index.html

Я бы порекомендовал вам взглянуть на SUDS

"Suds - это легкий Python-клиент SOAP для использования веб-сервисов".

Существует относительно новая библиотека, которая является очень многообещающей и хотя все еще плохо документированной, кажется очень чистой и питонской: python zeep.

Смотрите также этот ответ для примера.

Я недавно наткнулся на ту же проблему. Вот краткий обзор моего решения:

Необходимы базовые блоки кода

Ниже приведены обязательные базовые блоки кода вашего клиентского приложения.

  1. Раздел запроса сеанса: запрос сеанса у провайдера
  2. Раздел аутентификации сеанса: предоставьте учетные данные провайдеру
  3. Клиентский раздел: создать клиента
  4. Раздел заголовка безопасности: добавьте заголовок WS-Security на клиент
  5. Раздел потребления: потреблять доступные операции (или методы) по мере необходимости

Какие модули вам нужны?

Многие предлагали использовать модули Python, такие как urllib2; однако ни один из модулей не работает - по крайней мере, для этого конкретного проекта.

Итак, вот список модулей, которые вам нужно получить. Прежде всего, вам необходимо скачать и установить последнюю версию suds по следующей ссылке:

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

Кроме того, вам необходимо загрузить и установить модули request и suds_requests по следующим ссылкам соответственно (отказ от ответственности: я новичок в публикации здесь, поэтому я не могу опубликовать более одной ссылки на данный момент).

pypi.python.org/pypi/requests

pypi.python.org/pypi/suds_requests/0.1

После того, как вы успешно загрузите и установите эти модули, вы готовы к работе.

Код

В соответствии с шагами, описанными ранее, код выглядит следующим образом: Imports:

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
      },
 })

Zeep - достойная SOAP-библиотека для Python, которая соответствует тому, что вы просите: http://docs.python-zeep.org/

Прямо сейчас (по состоянию на 2008) все библиотеки SOAP, доступные для Python, отстой. Я рекомендую избегать SOAP, если это возможно. В прошлый раз, когда мы были вынуждены использовать веб-сервис SOAP из Python, мы написали оболочку на C#, которая обрабатывает SOAP с одной стороны и говорит COM с другой.

Я периодически ищу удовлетворительный ответ на этот вопрос, но пока не повезло. Я использую soapUI + запросы + ручной труд.

Я отказался и использовал Java в последний раз, когда мне нужно было это сделать, и просто несколько раз отказывался от последнего раза, когда я хотел это сделать, но это было не существенно.

После успешного использования библиотеки запросов в прошлом году с RESTful API в Project Place мне пришло в голову, что, возможно, я мог бы просто свернуть запросы SOAP, которые я хочу отправить, аналогичным образом.

Оказывается, это не так уж сложно, но это отнимает много времени и подвержено ошибкам, особенно если поля имеют непоследовательные имена (у того, над которым я сейчас работаю сегодня, есть 'jobId', JobId'и'JobID'. Я использую soapUI для загрузки WSDL, чтобы упростить извлечение конечных точек и т. д. и выполнить некоторое ручное тестирование. До сих пор мне повезло, что на меня не повлияли изменения в любом WSDL, который я использую.

Это неправда. SOAPpy не работает с Python 2.5 - он работает, хотя он очень простой и действительно очень простой. Если вы хотите поговорить с более сложным веб-сервисом, ZSI - ваш единственный друг.

По-настоящему полезная демонстрация, которую я нашел, находится по адресу http://www.ebi.ac.uk/Tools/webservices/tutorials/python - это действительно помогло мне понять, как работает ZSI.

Если вы катаетесь самостоятельно, я настоятельно рекомендую посмотреть на http://effbot.org/zone/element-soap.htm.

#!/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']))

SOAPpy теперь устарел, AFAIK, заменен на ZSL. Это спорный вопрос, потому что я не могу заставить ни одного работать, и тем более компилировать, на Python 2.5 или Python 2.6

Другие вопросы по тегам