Wie kann ich einen WSDL (SOAP) -Webdienst in Python nutzen?

124

Ich möchte einen WSDL SOAP-basierten Webdienst in Python verwenden. Ich habe mir den Dive Into Python- Code angesehen, aber das SOAPpy-Modul funktioniert unter Python 2.5 nicht.

Ich habe versucht, Schaum zu verwenden, der teilweise funktioniert, aber mit bestimmten Typen bricht (suds.TypeNotFound: Typ nicht gefunden: 'item').

Ich habe mir auch Client angesehen, aber dies scheint WSDL nicht zu unterstützen.

Ich habe mir ZSI angesehen, aber es sieht sehr komplex aus. Hat jemand einen Beispielcode dafür?

Die WSDL lautet https://ws.pingdom.com/soap/PingdomAPI.wsdl und funktioniert problemlos mit dem PHP 5 SOAP-Client.

Davidmytton
quelle
3
Würden Sie erwägen, Ihre akzeptierte Antwort zu ändern? Die aktuell akzeptierte Antwort ist -1 und es gibt eine andere Antwort mit +19. Ich weiß, dass dies von 2008 ist; Ich schlage nur vor.
Mark E. Haase
SUDS funktionierte nicht, da es die WSDL nicht richtig analysieren konnte, aber ansonsten eine gute Wahl wäre. Also habe ich die Antwort in ein Tutorial von Dive Into Python geändert, das einige Alternativen bietet. Als Randnotiz hat Pingdom jetzt eine REST-API pingdom.com/services/api-documentation-rest mit Client-Bibliotheken unter blog.pingdom.com/2011/04/11/pingdom-rest-api-wrappers
davidmytton

Antworten:

49

Ich würde empfehlen, dass Sie sich SUDS ansehen

"Suds ist ein leichter SOAP-Python-Client für die Nutzung von Webdiensten."

Yusufk
quelle
Abgeordnet. Suds machte für mich sofort Sinn, keine Klassengenerierung, es lädt die WSDL live und erstellt ein Objekt, das Sie sofort daraus verwenden können.
EnigmaCurry
19
Suds hat ein unendliches Rekursionsproblem beim Öffnen von WSDL mit rekursiven Importen. Dies wird von Suds als Blockierungsfehler angesehen. Das Problem wurde vor über 3 Jahren erstellt, aber noch nicht behoben. fedorahosted.org/suds/ticket/239 Ich frage mich, ob Suds für 2012 geeignet ist.
Buttons840
2
Schaum scheint tot zu sein. Es lebe SUDS - dies scheint die aktive Gabel zu sein.
Nerdoc
3
Dies ist die beste Antwort, aber wenn jemand nach einer Antwort sucht, die heute funktioniert, sollten Sie Zeep in Betracht ziehen , wie auch die neueren Antworten vermuten lassen.
Tobias Feil
25

Es gibt eine relativ neue Bibliothek, die sehr vielversprechend ist und, obwohl sie noch schlecht dokumentiert ist, sehr sauber und pythonisch erscheint: Python Zeep .

Siehe auch diese Antwort für ein Beispiel.

Lorenzog
quelle
2
+1 dafür. Ich habe heute Zeep ausprobiert und es war überraschend einfach zu bedienen. Konnte einen Soap 1.1 / 1.2-Dienst mit 3 Codezeilen nutzen und aufrufen.
Jagu
20

Ich bin kürzlich auf das gleiche Problem gestoßen. Hier ist die Zusammenfassung meiner Lösung:

Grundlegende Codeblöcke werden benötigt

Im Folgenden sind die erforderlichen grundlegenden Codeblöcke Ihrer Clientanwendung aufgeführt

  1. Sitzungsanforderungsabschnitt: Fordern Sie eine Sitzung mit dem Anbieter an
  2. Abschnitt zur Sitzungsauthentifizierung: Geben Sie dem Anbieter Anmeldeinformationen an
  3. Client-Bereich: Erstellen Sie den Client
  4. Abschnitt "Sicherheitskopf": Fügen Sie dem Client den WS-Sicherheitskopf hinzu
  5. Verbrauchsabschnitt: Verbrauchen Sie verfügbare Vorgänge (oder Methoden) nach Bedarf

Welche Module benötigen Sie?

Viele schlugen vor, Python-Module wie urllib2 zu verwenden. Keines der Module funktioniert jedoch - zumindest für dieses spezielle Projekt.

Hier ist die Liste der Module, die Sie benötigen. Zunächst müssen Sie die neueste Version von Schaum über den folgenden Link herunterladen und installieren:

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

Darüber hinaus müssen Sie Anforderungs- und suds_requests-Module von den folgenden Links herunterladen und installieren (Haftungsausschluss: Ich bin neu hier, daher kann ich vorerst nicht mehr als einen Link veröffentlichen).

pypi.python.org/pypi/requests

pypi.python.org/pypi/suds_requests/0.1

Sobald Sie diese Module erfolgreich heruntergeladen und installiert haben, können Sie loslegen.

Der Code

Nach den zuvor beschriebenen Schritten sieht der Code folgendermaßen aus: Importe:

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

Sitzungsanforderung und Authentifizierung:

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

Erstellen Sie den Client:

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

WS-Sicherheitskopf hinzufügen:

...
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)

Bitte beachten Sie, dass diese Methode den in Abb.1 dargestellten Sicherheitsheader erstellt. Daher kann Ihre Implementierung abhängig vom richtigen Sicherheitsheaderformat variieren, das vom Eigentümer des von Ihnen genutzten Dienstes bereitgestellt wird.

Verbrauchen Sie die relevante Methode (oder Operation):

result=client.service.methodName(Inputs)

Protokollierung :

Eine der besten Methoden bei solchen Implementierungen wie dieser ist die Protokollierung, um zu sehen, wie die Kommunikation ausgeführt wird. Falls es ein Problem gibt, erleichtert es das Debuggen. Der folgende Code führt die grundlegende Protokollierung durch. Sie können jedoch zusätzlich zu den im Code dargestellten Aspekten viele Aspekte der Kommunikation protokollieren.

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

Ergebnis:

Hier ist das Ergebnis in meinem Fall. Beachten Sie, dass der Server HTTP 200 zurückgegeben hat. Dies ist der Standard-Erfolgscode für die HTTP-Anforderungsantwort.

(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
      },
 })
Teddy Belay
quelle
1
Könnte erwähnenswert sein, dass dies suds_requestwährend der Installation fehlschlägt. Wenn Sie also eine suds-jurkoGabel verwenden, können Sie diese installieren, suds_requestdie für die Verwendung mit Jurkos Version von Schaum angepasst wurde:pip install git+https://github.com/chrcoe/suds_requests.git@feature/python3_suds_jurko
Errata
7

Derzeit (Stand 2008) saugen alle für Python verfügbaren SOAP-Bibliotheken. Ich empfehle, SOAP nach Möglichkeit zu vermeiden. Als wir das letzte Mal gezwungen waren, einen SOAP-Webdienst von Python zu verwenden, haben wir einen Crapper in C # geschrieben, der die SOAP auf der einen Seite handhabte und COM auf der anderen Seite aussprach.

Matthew Scouten
quelle
15
Das klingt nach einer wahnsinnig komplizierten Art, ein einfaches Protokoll zu verwenden, das auf XML und http basiert.
Ddaa
1
Zu der Zeit, 2008, war dies die Methode, die am wenigsten für unsere Bedürfnisse saugte. Ich scheine mich zu erinnern, dass dieser bestimmte Webdienst äußerst wählerisch in Bezug auf etwas war, bei dem alle Python-Bibliotheken falsch lagen.
Matthew Scouten
1
2019, Python Zeep, Schaum, immer noch anfällig für viele Probleme mit der Analyse von Inkompatibilitäten. Wenn WSDL-Dokumente schlecht gepflegt werden, lösen diese Module Ausnahmen wie ein Non-Stop-Firecracker aus.
Mootmoot
6

Ich suche regelmäßig nach einer zufriedenstellenden Antwort darauf, aber bisher kein Glück. Ich benutze soapUI + Anfragen + Handarbeit.

Ich gab auf und verwenden Java das letzte Mal , dass ich brauchte , dies zu tun, und gab nur ein paar Mal das letzte Mal , bis ich wollte , dies zu tun, aber es war nicht wesentlich.

Nachdem ich die Anforderungsbibliothek letztes Jahr erfolgreich mit der RESTful-API von Project Place verwendet hatte, kam mir der Gedanke, dass ich die SOAP-Anforderungen, die ich auf ähnliche Weise senden möchte, möglicherweise einfach per Hand rollen könnte.

Es stellt sich heraus, dass dies nicht allzu schwierig ist, aber es ist zeitaufwändig und fehleranfällig, insbesondere wenn Felder inkonsistent benannt sind (das Feld, an dem ich heute arbeite, hat 'jobId', JobId 'und' JobID '. Ich verwende soapUI zum Laden die WSDL, um das Extrahieren von Endpunkten usw. und das Durchführen manueller Tests zu vereinfachen. Bisher hatte ich das Glück, nicht von Änderungen an einer von mir verwendeten WSDL betroffen zu sein.

Hywel Thomas
quelle
3

Es ist nicht wahr, dass SOAPpy nicht mit Python 2.5 funktioniert - es funktioniert, obwohl es sehr einfach und wirklich sehr, sehr einfach ist. Wenn Sie mit einem komplizierteren Webservice sprechen möchten, ist ZSI Ihr einziger Freund.

Die wirklich nützliche Demo, die ich gefunden habe, ist unter http://www.ebi.ac.uk/Tools/webservices/tutorials/python zu finden - dies hat mir wirklich geholfen zu verstehen, wie ZSI funktioniert.

zgoda
quelle
1
Die Installation von python setup.py gibt Fehler mit der neuesten Version. Die neueste Entwicklerkopie könnte funktionieren, aber das ist ein Schmerz.
Davidmytton
1

SOAPpy ist jetzt veraltet, AFAIK, ersetzt durch ZSL. Es ist ein strittiger Punkt, weil ich weder Python 2.5 noch Python 2.6 zum Laufen bringen kann, geschweige denn kompilieren kann

der Blechmann
quelle
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']))
Den Bach runter
quelle
Die Bibliothek
Down the Stream
Beispielausgabe: ... DEBUG: pysimplesoap.helpers: complexContent / simpleType / element string = string [u'StockQuote '] GetQuote: <StockQuotes> <Stock> <Symbol> GOOG </ Symbol> <Last> 816.13 </ Last> <Datum> 23.03.2017 </ Datum> <Zeit>11:41 Uhr </ Zeit> <Ändern>-13,46 </ Ändern> <Öffnen> 820,01 </ Öffnen> <Hoch> 822,57 </ Hoch> <Niedrig> 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
schlägt auf Python3 in pysimplesoap / client.py fehl: 757 - 'dict' Objekt hat kein Attribut 'iteritems'
ierdna
Anscheinend ist die mit PIP gelieferte Version defekt. müssen es manuell von GIT installieren - es behebt Dinge
ierdna
Guter Punkt: siehe diesen Link: stackoverflow.com/questions/13998492/iteritems-in-python "dict.iteritems wurde entfernt, weil dict.items jetzt das tut, was dict.iteritems in Python 2 getan hat ..."
Down the Stream