Comment puis-je consommer un service web WSDL (SOAP) en Python?
je veux utiliser un service web basé sur WSDL SOAP en Python. J'ai regardé le plonger dans le code de Python, mais le module SOAPpy ne fonctionne pas sous Python 2.5.
j'ai essayé d'utiliser suds qui fonctionne en partie, mais casse avec certains types (suds.TypeNotFound: Type non trouvé: 'item').
j'ai aussi regardé Client mais cela ne semble pas supporter WSDL.
et j'ai regardé ZSI mais il semble très complexe. Quelqu'un at-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 SOAP PHP 5.
11 réponses
je sais que c'est un vieux fil, mais il apparaissait au sommet des résultats de Google donc je voulais partager une discussion plus actuelle sur Python et SOAP.
voir: http://www.diveintopython.net/soap_web_services/index.html
j'ai récemment trébuché sur le même problème. Voici le résumé de ma solution:
blocs de code constituant de base nécessaires
ce qui suit sont les blocs de code de base requis de votre application client
- section de demande de Session: demande de session avec le fournisseur
- section d'authentification de Session: fournir des justificatifs d'identité au fournisseur
- section Client: créer le Client
- Sécurité section d'en-Tête: ajouter le WS-Security-Tête du Client
- section consommation: consommer les opérations (ou les méthodes) disponibles au besoin
de quels modules avez-vous besoin?
beaucoup ont suggéré D'utiliser des modules Python tels que urllib2 ; cependant, aucun des modules ne fonctionne-au moins pour ce particulier projet.
Donc, voici la liste des modules que vous devez obtenir. Tout d'abord, vous devez télécharger et installer la dernière version de la mousse à partir du lien suivant:
pypi.python.org/pypi/suds-jurko/0.4.1.jurko.2
en outre, vous devez télécharger et installer les modules requests et suds_requests à partir des liens suivants respectivement (disclaimer: je suis nouveau à poster ici, donc je ne peux pas poster plus qu'un lien pour l'instant).
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 pouvez y aller.
le code
suivant les étapes décrites plus haut, 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 l'authentification:
username=input('Username:')
password=input('password:')
session = requests.session()
session.auth=(username, password)
créer le Client:
client = Client(WSDL_URL, faults=False, cachingpolicy=1, location=WSDL_URL, transport=suds_requests.RequestsTransport(session))
ajouter WS-Security Header:
...
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é à la figure 1.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 consommez.
consomment la méthode pertinente (ou fonctionnement):
result=client.service.methodName(Inputs)
Journalisation :
l'une des meilleures pratiques dans de telles implémentations est la journalisation pour voir comment la communication est exécutée. En cas de problème, cela facilite le débogage. Le code suivant fait 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 retourné HTTP 200. C'est le code de succès 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
},
})
il y a une bibliothèque relativement nouvelle qui est très prometteuse et encore mal documentée, qui semble très propre et pythonique: Python zeep .
Voir aussi cette réponse pour un exemple.
en ce moment (à partir de 2008), toutes les bibliothèques SOAP disponibles pour Python suck. Je recommande d'éviter le savon si possible. La dernière fois que nous avons été forcés d'utiliser un service Web SOAP de Python, nous avons écrit un wrapper en C# qui manipulait le SOAP d'un côté et parlait COM out de l'autre.
je cherche périodiquement une réponse satisfaisante à cela, mais pas de chance jusqu'à présent. J'utilise soapUI + demandes + travail manuel.
j'ai abandonné et utilisé Java la dernière fois que je ai eu besoin de pour faire ceci, et j'ai simplement abandonné quelques fois la dernière fois que je voulais pour faire ceci, mais ce n'était pas essentiel.
ayant utilisé avec succès la bibliothèque de requêtes l'an dernier avec L'API RESTful de Project Place, il m'est venu à l'esprit que peut-être je pourrais juste faire rouler les demandes de savon que je veux envoyer d'une manière similaire.
S'avère que ce n'est pas trop difficile, mais est longue et sujette à l'erreur, surtout si les champs sont nommés de façon incohérente (celui sur lequel je travaille actuellement a 'jobId', JobId' et 'JobID'. J'utilise soapUI pour charger le WSDL pour le rendre plus facile à extraire les points terminaux etc et effectuer quelques tests manuels. Jusqu'à présent, j'ai été chanceux de ne pas avoir été touché par des modifications à n'importe quel WSDL que j'utilise.
Zeep est une bibliothèque de savon décente pour Python qui correspond à ce que vous demandez: http://docs.python-zeep.org
ce n'est pas vrai SOAPpy ne fonctionne pas avec Python 2.5 - cela fonctionne, bien que ce soit très simple et vraiment, vraiment basique. Si vous voulez parler à un service Web plus compliqué, 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.
si vous roulez la vôtre, je vous recommande vivement de regarder http://effbot.org/zone/element-soap.htm .
SOAPpy est désormais obsolète, AFAIK, remplacé par ZSL. C'est un point discutable, parce que je ne peux pas faire fonctionner l'un ou l'autre, encore moins compiler, sur Python 2.5 ou Python 2.6
#!/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']))