In this serie of section, you will find several interoperability examples using two important SOAP libraries for Python: SOAPpy and ZSI, to consume Java WSDP or .NET web services.
Let's start using SOAPpy, it's a very easy and relatively powerfull maen to consume a web service from Python. I assume here you have a recent Python install plus all the required packages installed for the use of SOAPpy: fpconst and PyXML. To test your PyXML install, type the following code in your Python command-line:
>>> import xml >>>
If you don't have any error message, your package PyXML is correctly installed. Do the same check with fpconst:
>>> import fpconst >>>
And finally with SOAPpy:
>>> import SOAPpy >>>
If you encounter any error, just install the package needed.
To make a SOAP client for a Java WSDP web service, with SOAPpy, you need to call the remote procedure and specify explicitely the parameter names. Let's see how to do that for my web service:
Example 4-1. Simple Python SOAP client consuming my readLS() remote procedure.
from SOAPpy import SOAPProxy url = 'http://www.pascalbotte.be:80/rcx-ws/rcx' # define the namespace namespace = 'http://phonedirlux.homeip.net/types' server = SOAPProxy(url) # if you want to see the SOAP message exchanged # uncomment the two following lines #server.config.dumpSOAPOut = 1 #server.config.dumpSOAPIn = 1 # we see here how to specify the parameter name in the call # (String_1) print 'Light sensor simulation: ' + server._ns(namespace).readLS(String_1 = "Your message or e-mail")
Once again, you will easily add the other simple call: readLSpercent() (returning the value of the light sensor, in percent, of my brick) and readTemp() (returning the temperature).
# the name of the parameter 'int_1' must be the same than # the one you will find in the wsdl print 'Light sensor value: ' + server._ns(namespace).readLSpercent(int_1 = "1") print 'Temperature sensor value: ' + server._ns(namespace).readTemp(int_1 = "1")
And that's all for the calls returning simple type, next section we will see how to handle complex types returned by the web service.
We just use the same template here, each call use the function _ns(), allowing to specify the namespace for the remote procedure (like in the wsdl). If you need to send a complex type as a parameter, shift to the section which explain how to consume a .NET web service using python.
# we start with the status() procedure, which return # the object rcxResponse containing some internal # values of my RCX brick. rcxResponse = server._ns(namespace).status() print 'Rcx message: '.ljust(20) , rcxResponse.status + \ '\nBattery level: '.ljust(20) , rcxResponse.battery + \ '\nInternal clock: '.ljust(20) , rcxResponse.currentTime + \ '\nMemory free: '.ljust(20) , rcxResponse.memory # the function collInt() (returning an array of integer) intarray = server._ns(namespace).collInt() print 'Remote procedure collInt() returning an array of integer:' for val in intarray : print val.rjust(5) # the function collPos() (returning an array of PosCol object PosColArray = server._ns(namespace).collPos() print 'Remote procedure collPos() returning an array of PosCol object:' for pc in PosColArray : print '[XPos]: '.ljust(10) + pc.XPos , '[YPos]: '.ljust(10) + pc.YPos
So we see how it is simple to use. The most important things are specify the namespace and the parameter name accordingly to the wsdl. With more experience, you will soon be able to easily find these info in any wsdl. And if you begin, just make a client with a well known tool and catch the SOAP message exchanged between your client and the web service you consume (eg: TcpTunnelGui). Knowing exactly the format of the SOAP message you have to send, it is easier to reproduce it in another language/platform and with other tools.
You can use the WSDL class to parse a WSDL and list, for you, all the methods available. And sometimes even the parameter name and type, took and returned by the methods. Test this code on a web service of your choice:
Example 4-2. How to parse a wsdl with SOAPpy.
from SOAPpy import WSDL url = 'http://www.pascalbotte.be/rcx-ws/rcx' # just use the path to the wsdl of your choice wsdlObject = WSDL.Proxy(url + '?WSDL') print 'Available methods:' for method in wsdlObject.methods.keys() : print method ci = wsdlObject.methods[method] # you can also use ci.inparams for param in ci.outparams : # list of the function and type # depending of the wsdl... print param.name.ljust(20) , param.type print
In the case of my web service, there is one method taking an object as param (and returning the same object): the method RcxQuery queryRcx(RcxQuery obj). The RcxQuery object contain two simple integer variable: "x" and "y". When trying to consume this method with Python and SOAPpy, I could not order the two variables (x and y) of the class RcxQuery in the SOAP message created by SOAPpy. Because of that I faced a serialize exception throwed by my web service: SOAPpy was not able to send the variable "x" in first position, followed by the variable "y".
Due to this limitation, we can't cover the case of a SOAPpy, Python client for the Infobel web service (.NET). So when designing a web service, if you want to avoid the loss of all the potential Python SOAPpy developer and client, do not expose procedure taking object as parameter ;-).
|Perl XML HTTP Post to a web service.|
My home page
|Python XML HTTP Post to send a SOAP message to a JWSDP or to a .NET web service.|