Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

The Python Web services developer: Python SOAP libraries, Part 2

With and without WSDL

Mike Olson, Principal Consultant, Fourthought, Inc.
Photo of Mike Olson
Mike Olson is a consultant and co-founder of Fourthought Inc., a software vendor and consultancy specializing in XML solutions for enterprise knowledge management applications. Fourthought develops 4Suite, and 4Suite Server, open source platforms for XML middleware. You can contact Mr. Olson at mike.olson@fourthought.com.
Uche Ogbuji (uche@ogbuji.net), Principal Consultant, Fourthought, Inc.
Photo of Uche Ogbuji
Uche Ogbuji is a consultant and co-founder of Fourthought Inc., a software vendor and consultancy specializing in XML solutions for enterprise knowledge management applications. Fourthought develops 4Suite, and 4Suite Server, open source platforms for XML middleware. Mr. Ogbuji is a Computer Engineer and writer born in Nigeria, living and working in Boulder, Colorado, USA. You can cont act Mr. Ogbuji at uche@ogbuji.net.

Summary:  Continuing their look at Python SOAP implementations, Mike Olson and Uche Ogbuji put the Zolera SOAP Infrastructure (ZSI) through its paces as a SOAP client and server library. They find that ZSI is possibly the best tool for SOAP use under Python right now.

Date:  26 Feb 2002
Level:  Introductory
Also available in:   Japanese

Activity:  14450 views
Comments:  

This month we continue our look at SOAP implementations for Python. In fact, we will take a close look at one we completely neglected to mention last time: the Zolera SOAP Infrastructure (ZSI). ZSI is the brain-child of Rich Salz, an active contributor to the Python/XML package, and veteran of several important standards efforts in Internet infrastructure and security. ZSI has been added as part of the Python Web Services project on SourceForge, which also hosts SOAPy, another Python/SOAP package we covered in the previous installment. We expect this confusing state of affairs will be resolved soon, perhaps with a merger of the SOAP packages.

ZSI is a purist's SOAP library. In particular, it is less concerned about handling any low-level protocol details: It deals with a stream of data that must be a properly-formatted SOAP message, and dispatches events to Python event handlers based on the parsed data. The upside of this strict focus is that ZSI is probably the most complete and compliant SOAP library for Python. The downside is that the ZSI user may have to do more work to actually put his or her Web services into play.

Setting up ZSI

To install ZSI 1.1, the latest version as of our writing, you need Python 2.0 or later. The instructions say you need PyXML 0.6 or later, but actually, you need version 0.6 or later, but earlier than 0.7. There were several significant API changes that appeared in PyXML 0.7 that break ZSI 1.1. This is a general problem issue while dealing with packages that depend on PyXML: if you get strange errors when using a package that states a dependency on PyXML 0.6, you might have understandably grabbed the latest available version of PyXML, which, unfortunately, will not work. The next release of ZSI will probably work with PyXML 0.7 and later, as the recent CVS activity seems to indicate. Grab PyXML 0.6.6 from SourceForge and unpack it, then build it:

$ python setup.py install

Download the ZSI package, unpack it, and build it the same way:

$ python setup.py install

This is the consistency that Python's distribution utilities (AKA distutils) brings to installing add-on Python packages.

Now that it's all installed, check out the doc directory, which has excellent documentation in HTML, PDF, postscript, and TeX format, using the same LaTeX tools as used in the Python documentation project.


Invoking client privilege

First of all, we looked at using ZSI as a SOAP client. In the last installment, we wrote a SOAP.py client that accesses a toy Web service that returns curses by Captain Haddock (ever popular to Tin Tin comic fans). We will write a client for the same server using ZSI. Unfortunately, we ran into a bit of a kink doing this. The most straightforward approach is the code in Listing 1, but it turns out that this requires the server to handle message parameters by their order as well as their name, but the Borland Delphi implementation with which the Captain Haddock server is implemented isn't so flexible, so it gets confused.


Listing 1: Attempt at a ZSI program to access the Captain Haddock SOAP service
		
  #http://xmethods.net/detail.html?id=175

import sys

#Import the ZSI client
from ZSI.client import Binding

u = '/scripts/Haddock.exe/soap/IHaddock'
n = 'urn:HaddockIntf-IHaddock'
b = Binding(url=u, ns=n, host='www.tankebolaget.se', port=80,
            tracefile=sys.stdout)

try:
  lang = sys.argv[1]
except IndexError:
  lang = 'us'

result = b.Curse(lang)

print 'What captain Haddock had to say: "%s"'%result



Because this simple approach would work with many SOAP 1.1 servers, let's have a look, even though it doesn't give us the expected result. First of all we import the ZSI client module, and the Binding class, which implements the machinery for setting up and invoking SOAP requests. Next we set up the components of the address of the SOAP end point. Note that we set up the host, the URL path, and the port separately. You cannot use a single URL, as you can with SOAP.py. These components are used to create a binding to the remote server.

Finally, we call the Curse method on the binding object to send the remote request, and we get back the result in the method return. But as we mentioned, this simple approach doesn't work with the Captain Haddock server. We must use a more complex structure to communicate the LangCode parameter to the server. The code in Listing 2 does the trick.


Listing 2: Working ZSI program to access the Captain Haddock SOAP service
		
  import sys

#Import the ZSI client
from ZSI import TC
from ZSI.client import Binding

u = '/scripts/Haddock.exe/soap/IHaddock'
n = 'urn:HaddockIntf-IHaddock'
b = Binding(url=u, host='www.tankebolaget.se', port=80, ns=n)

try:
  lang = sys.argv[1]
except IndexError:
  lang = 'us'

class CurseRequest:
    def __init__(self, langCode):
        self.LangCode = langCode

CurseRequest.typecode=TC.Struct(CurseRequest,
                                [TC.String('LangCode')],
                                'Curse',
                                inline=1)

try:
    result_list = b.RPC(u, 'Curse', CurseRequest(lang), TC.Any(aslist=1))
    #Extract the first returned parameter
    result = result_list[0]
    print 'What captain Haddock had to say: "%s"'%result
except:
    raise
    print 'reply=', b.reply_code
    print 'reply_msg=', b.reply_msg
    print 'headers=', b.reply_headers
    print 'data=', b.data


The TypeCode module allows a precise and extensible mapping between Python data types and SOAP data types. It has a set of built-in classes for String, Integer, etc. It also defines a Struct class for defining arbitrary data aggregations, and the special class Any which can be used to represent any built-in or derived type and thus is the basis of dynamic typing. These latter two classes are the key to navigating around the many interoperability problems in SOAP encoding that stem from different marshalling and unmarshalling of typed data. Even though we had to go through some contortions to get ZSI to align with the Delphi server we're addressing, at least ZSI gives you all the machinery to do so. With the other Python SOAP implementations we have had to hack at the client library code to sort out interoperability problems.

We then create a class, CurseRequest, which will be marshalled into the form required by the Captain Haddock server. We define an instance attribute for the required LangCode parameter. Then we assign the class a ZSI type code that marshals the LangCode value into a string. One note is the inline=1 specification, which disables marshalling using multi-reference values. By default, ZSI marshals structures using multi-reference, which means that you can express a value in one part of the SOAP message and refer to that same value by reference in another part of the SOAP message, in order to avoid duplication of the values. SOAP encoding multi-reference values are much less commonly used than just simple values, so it's odd that the default in ZSI's structure types is to be marshalled as multi-reference.

This detail and others seem to reinforce a comment Rich Salz, author of ZSI, made to us: that ZSI is actually designed primarily for complex Web services. He promises to make it a bit easier soon to use ZSI against the toys that seem to be the majority of published services.

The following illustrates the use of the example client code


$ python curse-zsi.py 
What captain Haddock had to say: "Polygraphs!"


It is quite easy to enable debugging and tracing in ZSI. Just pass a tracefile=sys.stdout parameter to the Binding initializer. After making this modification, the sample ZSI session looks like:


$ python curse-zsi-trace.py 
_________________________________ Thu Jan 31 10:25:09 2002 REQUEST:
<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" >
<SOAP-ENV:Body>
<Curse id="822b6dc">
<LangCode id="81089d0" xsi:type="xsd:string">us</LangCode>
</Curse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

_________________________________ Thu Jan 31 10:25:10 2002 RESPONSE:
Server: Microsoft-IIS/5.0
Date: Thu, 31 Jan 2002 17:18:37 GMT
Content-Type: text/xml
Content-Length: 524
Content:

<?xml version="1.0" encoding='UTF-8'?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema" 
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" 
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<NS1:CurseResponse xmlns:NS1="urn:HaddockIntf-IHaddock" 
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<NS1:return xsi:type="xsd:string">Sea-lice!</NS1:return>
</NS1:CurseResponse>
</SOAP-ENV:Body></SOAP-ENV:Envelope>
What captain Haddock had to say: "Sea-lice!"



Are you being served?

Setting up a ZSI server is simple enough. Listing 3 presents the same trivial calendar SOAP server we used as an example for SOAP.py in the last column. (See Resources.)


Listing 3: ZSI calendar SOAP server
		
  #!/usr/bin/env python

import sys, calendar

#Import the ZSI machinery
from ZSI import dispatch

def getMonth(year, month):
  return calendar.month(year, month)

def getYear(year):
  return calendar.calendar(year)

print "Starting server..."
dispatch.AsServer(port=8080)



Note that this is even easier than with SOAP.py. All you do is define a function for each method. With the required parameters, variable number and keyword arguments can be used as well for positional and named parameters. The dispatch.AsServer() call simply registers all the defined functions as SOAP methods and starts up the HTTP server on the specified port.

One problem is that ZSI's server code doesn't seem to have an easy way of aligning the namespace used in the request. The documents claim there is a dispatch.GetNS() function that returns the namespace that was used in the request element, but this doesn't seem to be the case. This is a pretty serious omission as the namespace used in the request is an essential part of that request.

The following ZSI client code exercises the calendar we just wrote:


Listing 4: ZSI calendar SOAP client
		
  #http://xmethods.net/detail.html?id=175

import sys

#Import the ZSI client
from ZSI.client import Binding

u = ''
n = 'http://uche.ogbuji.net/eg/ws/simple-cal'
b = Binding(url=u, ns=n, host='localhost', port=8080)

result = b.getMonth(2002, 2)
print result[0]

result = b.getYear(2002)
print result[0]



To test it, just start the server using "$ python calendar-zsi.py" in one console, then in another:


$ python2.1 cal-client.py 
February 2002
Mo Tu We Th Fr Sa Su
             1  2  3
 4  5  6  7  8  9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28
2002

       January                  February                    March
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
    1  2  3  4  5  6                   1  2  3                   1  2  3
 7  8  9 10 11 12 13       4  5  6  7  8  9 10       4  5  6  7  8  9 10
14 15 16 17 18 19 20      11 12 13 14 15 16 17      11 12 13 14 15 16 17
21 22 23 24 25 26 27      18 19 20 21 22 23 24      18 19 20 21 22 23 24
28 29 30 31               25 26 27 28               25 26 27 28 29 30 31

        April                      May                      June
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7             1  2  3  4  5                      1  2
 8  9 10 11 12 13 14       6  7  8  9 10 11 12       3  4  5  6  7  8  9
15 16 17 18 19 20 21      13 14 15 16 17 18 19      10 11 12 13 14 15 16
22 23 24 25 26 27 28      20 21 22 23 24 25 26      17 18 19 20 21 22 23
29 30                     27 28 29 30 31            24 25 26 27 28 29 30

        July                     August                   September
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7                1  2  3  4                         1
 8  9 10 11 12 13 14       5  6  7  8  9 10 11       2  3  4  5  6  7  8
15 16 17 18 19 20 21      12 13 14 15 16 17 18       9 10 11 12 13 14 15
22 23 24 25 26 27 28      19 20 21 22 23 24 25      16 17 18 19 20 21 22
29 30 31                  26 27 28 29 30 31         23 24 25 26 27 28 29
                                                    30

       October                  November                  December
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
    1  2  3  4  5  6                   1  2  3                         1
 7  8  9 10 11 12 13       4  5  6  7  8  9 10       2  3  4  5  6  7  8
14 15 16 17 18 19 20      11 12 13 14 15 16 17       9 10 11 12 13 14 15
21 22 23 24 25 26 27      18 19 20 21 22 23 24      16 17 18 19 20 21 22
28 29 30 31               25 26 27 28 29 30         23 24 25 26 27 28 29
                                                    30 31



Conclusion

ZSI, which we completely missed in the last column, turns out to be the most mature and useable SOAP library for Python. The author expects to have version 1.2 out soon, which addresses some of the complaints we've made in this article.

Now that we have surveyed Python SOAP packages, and looked closely at a couple of them, in the next installment, we will look at how Python SOAP implementations interoperate with each other.


Resources

About the authors

Photo of Mike Olson

Mike Olson is a consultant and co-founder of Fourthought Inc., a software vendor and consultancy specializing in XML solutions for enterprise knowledge management applications. Fourthought develops 4Suite, and 4Suite Server, open source platforms for XML middleware. You can contact Mr. Olson at mike.olson@fourthought.com.

Photo of Uche Ogbuji

Uche Ogbuji is a consultant and co-founder of Fourthought Inc., a software vendor and consultancy specializing in XML solutions for enterprise knowledge management applications. Fourthought develops 4Suite, and 4Suite Server, open source platforms for XML middleware. Mr. Ogbuji is a Computer Engineer and writer born in Nigeria, living and working in Boulder, Colorado, USA. You can cont act Mr. Ogbuji at uche@ogbuji.net.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services
ArticleID=11643
ArticleTitle=The Python Web services developer: Python SOAP libraries, Part 2
publish-date=02262002
author1-email=mike.olson@fourthought.com
author1-email-cc=
author2-email=uche@ogbuji.net
author2-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers