Comment puis-je utiliser un service Web WSDL (SOAP) en Python?


124

Je souhaite utiliser un service Web basé sur WSDL SOAP en Python. J'ai regardé le code Dive Into Python mais le module SOAPpy ne fonctionne pas sous Python 2.5.

J'ai essayé d'utiliser de la mousse qui fonctionne en partie, mais qui rompt avec certains types (suds.TypeNotFound: Type not found: 'item').

J'ai également regardé Client mais cela ne semble pas prendre en charge WSDL.

Et j'ai regardé ZSI mais cela semble très complexe. Quelqu'un a-t-il un exemple de code pour cela?

Le WSDL est https://ws.pingdom.com/soap/PingdomAPI.wsdl et fonctionne très bien avec le client PHP 5 SOAP.


3
Envisageriez-vous de changer votre réponse acceptée? La réponse actuellement acceptée est -1, et il y a une autre réponse avec +19. Je sais que cela date de 2008; Je suggère juste.
Mark E. Haase

SUDS ne fonctionnait pas car il ne pouvait pas analyser correctement le WSDL mais serait un bon choix sinon. J'ai donc changé la réponse en un tutoriel de Dive Into Python qui propose des alternatives. En remarque, Pingdom a maintenant une API REST pingdom.com/services/api-documentation-rest avec des bibliothèques clientes sur blog.pingdom.com/2011/04/11/pingdom-rest-api-wrappers
davidmytton

Réponses:


49

Je vous recommande de jeter un œil à SUDS

"Suds est un client python SOAP léger pour la consommation de services Web."


Appuyé. Suds a eu un sens immédiat pour moi, pas de génération de classe, il charge le WSDL en direct et crée un objet que vous pouvez immédiatement utiliser.
EnigmaCurry

19
Suds a un problème de récursivité infinie lors de l'ouverture de WSDL avec des importations récursives. Ceci est considéré comme un bogue bloquant par Suds, et le problème a été créé il y a plus de 3 ans, mais il n'a pas encore été corrigé. fedorahosted.org/suds/ticket/239 Cela me fait me demander si Suds peut être utilisé en 2012?
Buttons840

2
la mousse semble morte. Vive SUDS - cela semble être la fourche active.
nerdoc

3
C'est la meilleure réponse, mais si quelqu'un cherche une réponse qui fonctionne aujourd'hui, considérez Zeep , comme le suggèrent également les nouvelles réponses.
Tobias Feil

25

Il existe une bibliothèque relativement nouvelle, très prometteuse et encore mal documentée, qui semble très propre et pythonique: python zeep .

Voir également cette réponse pour un exemple.


2
+1 pour cela. J'ai essayé zeep aujourd'hui et c'était étonnamment facile à utiliser. A pu consommer et appeler un service Soap 1.1 / 1.2 avec 3 lignes de code.
Jagu

20

Je suis récemment tombé sur le même problème. Voici le synopsis de ma solution:

Blocs de code constitutifs de base nécessaires

Voici les blocs de code de base requis de votre application cliente

  1. Section de demande de session: demander une session avec le fournisseur
  2. Section d'authentification de session: fournissez les informations d'identification au fournisseur
  3. Section client: créer le client
  4. Section d'en-tête de sécurité: ajoutez l'en-tête WS-Security au client
  5. Section consommation: consommer les opérations (ou méthodes) disponibles selon les besoins

De quels modules avez-vous besoin?

Beaucoup ont suggéré d'utiliser des modules Python tels que urllib2; cependant, aucun des modules ne fonctionne, du moins pour ce projet particulier.

Alors, voici la liste des modules dont vous avez besoin. Tout d'abord, vous devez télécharger et installer la dernière version de suds à partir du lien suivant:

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

De plus, vous devez télécharger et installer respectivement les requêtes et les modules suds_requests à partir des liens suivants (avertissement: je suis nouveau pour publier ici, je ne peux donc pas publier plus d'un lien pour le moment).

pypi.python.org/pypi/requests

pypi.python.org/pypi/suds_requests/0.1

Une fois que vous avez téléchargé et installé ces modules avec succès, vous êtes prêt à partir.

Le code

En suivant les étapes décrites précédemment, le code ressemble à ce qui suit: Importations:

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

Demande de session et authentification:

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

Créez le client:

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

Ajouter l'en-tête 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)

Veuillez noter que cette méthode crée l'en-tête de sécurité représenté sur la figure 1. Ainsi, votre implémentation peut varier en fonction du format d'en-tête de sécurité correct fourni par le propriétaire du service que vous utilisez.

Consommez la méthode (ou l'opération) appropriée:

result=client.service.methodName(Inputs)

Journalisation :

L'une des meilleures pratiques dans des implémentations telles que celle-ci consiste à se connecter pour voir comment la communication est exécutée. En cas de problème, cela facilite le débogage. Le code suivant effectue la journalisation de base. Cependant, vous pouvez enregistrer de nombreux aspects de la communication en plus de ceux décrits dans le code.

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

Résultat:

Voici le résultat dans mon cas. Notez que le serveur a renvoyé HTTP 200. Il s'agit du code de réussite standard pour la requête-réponse 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
Cela vaut peut-être la peine de dire que suds_requestcela échouera lors de l'installation, donc si vous utilisez suds-jurkofork, vous pouvez installer suds_requestce qui a été adapté pour fonctionner avec la version jurko de suds:pip install git+https://github.com/chrcoe/suds_requests.git@feature/python3_suds_jurko
errata

7

À l'heure actuelle (à partir de 2008), toutes les bibliothèques SOAP disponibles pour Python sont nulles. Je recommande d'éviter le savon si possible. La dernière fois que nous avons été obligés d'utiliser un service Web SOAP de Python, nous avons écrit un wrapper en C # qui gérait le SOAP d'un côté et parlait COM de l'autre.


15
Cela ressemble à une manière incroyablement compliquée d'utiliser un protocole simple basé sur xml et http.
ddaa

1
À l'époque, en 2008, c'était la méthode qui avait le moins sucé nos besoins. Il me semble me souvenir que ce service Web particulier était extrêmement pointilleux sur quelque chose que toutes les bibliothèques Python se trompaient.
Matthew Scouten

1
2019, python zeep, mousse, toujours sujet à de nombreux problèmes d'incompatibilité d'analyse. Une mauvaise maintenance des documents wsdl fera que ces modules lancent des exceptions comme un pétard non-stop.
mootmoot


6

Je recherche périodiquement une réponse satisfaisante à cela, mais pas de chance pour l'instant. J'utilise soapUI + demandes + travail manuel.

J'ai abandonné et utilisé Java la dernière fois que j'ai eu besoin de faire cela, et j'ai simplement abandonné quelques fois la dernière fois que je voulais le faire, mais ce n'était pas essentiel.

Après avoir utilisé avec succès la bibliothèque de requêtes l'année dernière avec l'API RESTful de Project Place, il m'est venu à l'esprit que je pourrais peut-être simplement gérer les requêtes SOAP que je souhaite envoyer de la même manière.

Il s'avère que ce n'est pas trop difficile, mais cela prend du temps et est sujet aux erreurs, surtout si les champs sont nommés de manière incohérente (celui sur lequel je travaille actuellement a 'jobId', JobId 'et' JobID '. J'utilise soapUI pour charger le WSDL pour faciliter l'extraction des points de terminaison, etc. et effectuer des tests manuels Jusqu'à présent, j'ai eu la chance de ne pas avoir été affecté par les modifications apportées à tout WSDL que j'utilise.


3

Ce n'est pas vrai que SOAPpy ne fonctionne pas avec Python 2.5 - cela fonctionne, bien que ce soit très simple et vraiment très basique. Si vous souhaitez parler à un service Web plus complexe, ZSI est votre seul ami.

La démo vraiment utile que j'ai trouvée est à http://www.ebi.ac.uk/Tools/webservices/tutorials/python - cela m'a vraiment aidé à comprendre comment fonctionne ZSI.


1
l'installation de python setup.py donne des erreurs avec la dernière version. La dernière copie de développement peut fonctionner, mais c'est difficile à faire.
davidmytton le


1

SOAPpy est désormais obsolète, AFAIK, remplacé par ZSL. C'est un point discutable, car je ne peux pas faire fonctionner l'un ou l'autre, et encore moins compiler, sur Python 2.5 ou 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']))


exemple de sortie: ... DEBUG: pysimplesoap.helpers: complexContent / simpleType / element string = string [u'StockQuote '] GetQuote: <StockQuotes><Stock><Symbol>GOOG</Symbol> <Last> 816.13 </Last> <Date> 23/03/2017</Date><Heure> 11h41</Heure><Change>-13.46</Change><Open>820.01</Open><High>822.57</High> <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> 663.28 - 853.50 </AnnRange> <Earns>27.88</Earns><PE>29.28</PE> <Name> Alphabet Inc. </Name> </Stock> </StockQuotes>
Down the Stream

échoue sur Python3 dans pysimplesoap / client.py: 757 - l'objet 'dict' n'a pas d'attribut 'iteritems'
ierdna

apparemment, la version fournie avec PIP est cassée. doivent l'installer manuellement à partir de GIT - il corrige les choses
ierdna

Bon point: voir ce lien: stackoverflow.com/questions/13998492/iteritems-in-python "dict.iteritems a été supprimé car dict.items fait maintenant ce que dict.iteritems a fait en python 2 ..."
Down the Stream
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.