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

124

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

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

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

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

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

davidmytton
источник
3
Вы бы подумали об изменении принятого ответа? В настоящее время принят ответ -1, и есть еще один ответ с +19. Я знаю, что это с 2008 года; Я просто предлагаю.
Марк Э. Хаасе
SUDS не работал, поскольку не мог правильно проанализировать WSDL, но в противном случае был бы хорошим выбором. Поэтому я изменил ответ на учебник от Dive Into Python, в котором есть несколько альтернатив. Кстати , у Pingdom теперь есть REST API pingdom.com/services/api-documentation-rest с клиентскими библиотеками на blog.pingdom.com/2011/04/11/pingdom-rest-api-wrappers
davidmytton

Ответы:

49

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

«Suds - это облегченный клиент SOAP на Python для использования веб-служб».

Yusufk
источник
Откомандирован. Suds сразу же обрел смысл для меня, без создания классов, он загружает WSDL вживую и создает объект, который вы можете немедленно использовать из него.
EnigmaCurry
19
Suds имеет проблему бесконечной рекурсии при открытии WSDL с рекурсивным импортом. Suds считает это ошибкой блокировки, и проблема была создана более 3 лет назад, но еще не исправлена. fedorahosted.org/suds/ticket/239 Это заставляет задуматься, подходит ли Suds для использования в 2012 году?
Buttons840
2
пена кажется мертвой. Да здравствует SUDS - похоже, это активная вилка.
nerdoc
3
Это лучший ответ, но если кто-то ищет ответ, который работает сегодня, подумайте о Zeep , как показывают и новые ответы.
Тобиас Фейл
25

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

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

lorenzog
источник
2
+1 за это. Я попробовал zeep сегодня, и он оказался на удивление простым в использовании. Мог использовать и вызывать сервис Soap 1.1 / 1.2 с 3 строками кода.
JAGU
20

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

Необходимые базовые составляющие кодовые блоки

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

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

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

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

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

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

Кроме того, вам необходимо загрузить и установить модули запросов и 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
      },
 })
Тедди Белэй
источник
1
Может быть, стоит сказать, что suds_requestпри установке произойдет сбой, поэтому, если вы используете suds-jurkofork, вы можете установить, suds_requestкоторый был адаптирован для работы с версией suds от jurko:pip install git+https://github.com/chrcoe/suds_requests.git@feature/python3_suds_jurko
errata
7

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

Мэтью Скоутен
источник
15
Звучит как безумно сложный способ использовать простой протокол, основанный на xml и http.
ddaa
1
В то время, в 2008 году, это был метод, который меньше всего отвечал нашим потребностям. Кажется, я помню, что этот конкретный веб-сервис был чрезвычайно разборчив в том, что все библиотеки Python ошибались.
Мэтью Скоутен
1
2019, python zeep, suds, по-прежнему подвержены множеству проблем несовместимости при синтаксическом анализе. Плохое обслуживание wsdl-документов приведет к тому, что эти модули будут генерировать исключение, как непрерывный фейерверк.
mootmoot
6

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

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

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

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

Хиуэл Томас
источник
3

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

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

Zgoda
источник
1
Установка python setup.py выдает ошибки в последней версии. Последняя версия для разработчиков может работать, но это больно делать.
Дэвидмиттон,
1

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

Железный Человек
источник
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']))
Вниз по течению
источник
библиотека
Down the Stream
пример вывода: ... DEBUG: pysimplesoap.helpers: complexContent / simpleType / element string = string [u'StockQuote '] GetQuote: <StockQuotes><Stock><Symbol>GOOG</Symbol> <Last> 816.13 </Last> <Дата> 3/23/2017 </ Дата> <Время> 11:41 утра </ Время> <Изменить> -13,46 </ Изменить> <Open> 820,01 </ Open> <высокий> 822,57 </ высокий> <Low> 812,26 </Low> <Volume> 1973140 </Volume> <MktCap> 564,29B </MktCap> <PreviousClose> 829,59 </PreviousClose> <PercentageChange> -1,62% </PercentageChange> <AnnRange> 663,28–853,50 </AnnRange> <Earns>27.88</Earns><PE>29.28</PE> <Name> Alphabet Inc. </Name> </Stock> </StockQuotes>
Down the Stream
не работает на Python3 в pysimplesoap / client.py: 757 - объект 'dict' не имеет атрибута 'iteritems'
ierdna
видимо, версия, которая идет с PIP, не работает. придется установить его вручную из GIT - он все исправляет
ierdna
Хороший момент: см. Эту ссылку: stackoverflow.com/questions/13998492/iteritems-in-python "dict.iteritems был удален, потому что dict.items теперь делает то, что dict.iteritems делал в python 2 ..."
Down the Stream