python编写SOAP服务
引用
简单对象访问协议(SOAP,全写为Simple Object Access Protocol)是一种标准化的通讯规范,主要用于Web服务(web service)中。SOAP的出现是为了简化网页服务器(Web Server)在从XML数据库中提取数据时,无需花时间去格式化页面,并能够让不同应用程序之间透过HTTP通讯协定,以XML格式互相交换彼此的数据,使其与编程语言、平台和硬件无关
参考:http://zh.wikipedia.org/wiki/SOAP
http://www.ibm.com/developerworks/cn/xml/x-sisoap/index.html
python的soap包
引用
Older libraries:
SOAPy: Was the "best," but no longer maintained. Does not work on Python 2.5+
ZSI: Very painful to use, and development is slow. Has a module called "SOAPpy", which is different than SOAPy (above).
"Newer" libraries:
SUDS: Very Pythonic, and easy to create WSDL-consuming SOAP clients. Creating SOAP servers is a little bit more difficult.
soaplib: Creating servers is easy, creating clients a little bit more challenging.
ladon: Creating servers is much like in soaplib (using a decorator). Ladon exposes more interfaces than SOAP at the same time without extra user code needed.
pysimplesoap: very lightweight but useful for both client and server - includes a web2py server integration that ships with web2py.
参考: http://stackoverflow.com/questions/206154/whats-the-best-soap-client-library-for-python-and-where-is-the-documentation-f
用SOAPpy编写的一个简单例子
SOAPpy包:http://pypi.python.org/pypi/SOAPpy/
A simple "Hello World" http SOAP server:
- import SOAPpy
- def hello():
- return "Hello World"
- server = SOAPpy.SOAPServer(("localhost", 8080))
- server.registerFunction(hello)
- server.serve_forever()
And the corresponding client:
- import SOAPpy
- server = SOAPpy.SOAPProxy("http://localhost:8080/")
- print server.hello()
soaplib编写soap server
选用soaplib,因为看对各包的简介,soaplib对服务器端的编写更加简单
soaplib包: http://pypi.python.org/pypi/soaplib/0.8.1
soaplib 2.0的安装
git clone git://github.com/soaplib/soaplib.git
cd soaplib
python setup.py install
参考:http://soaplib.github.com/soaplib/2_0/
soaplib2.0 和 wsgi webserver 编写的一个简单例子
Declaring a Soaplib Service
- import soaplib
- from soaplib.core.service import rpc, DefinitionBase
- from soaplib.core.model.primitive import String, Integer
- from soaplib.core.server import wsgi
- from soaplib.core.service import soap
- from soaplib.core.model.clazz import Array
- class HelloWorldService(DefinitionBase):
- @soap(String,Integer,_returns=Array(String))
- def say_hello(self,name,times):
- results = []
- for i in range(0,times):
- results.append('Hello, %s'%name)
- return results
- if __name__=='__main__':
- try:
- from wsgiref.simple_server import make_server
- soap_application = soaplib.core.Application([HelloWorldService], 'tns')
- wsgi_application = wsgi.Application(soap_application)
- server = make_server('localhost', 7789, wsgi_application)
- server.serve_forever()
- except ImportError:
- print "Error: example server code requires Python >= 2.5"
SOAP Client
- >>> from suds.client import Client
- >>> hello_client = Client('http://localhost:7789/?wsdl')
- >>> result = hello_client.service.say_hello("Dave", 5)
- >>> print result
- (stringArray){
- string[] =
- "Hello, Dave",
- "Hello, Dave",
- "Hello, Dave",
- "Hello, Dave",
- "Hello, Dave",
- }
soaplib 2.0 的一个bug
在运行上面的小例子时,服务器端报错:
......
File "/usr/local/lib/python2.6/dist-packages/soaplib-2.0.0_beta2-py2.6.egg/soaplib/core/_base.py", line 331, in parse_xml_string
return _parse_xml_string(xml_string, charset)
NameError: global name 'x' is not defined
修改源码包:/usr/local/lib/python2.6/dist-packages/soaplib-2.0.0_beta2-py2.6.egg/soaplib/core/_base.py
line 331
- ...
- def parse_xml_string(self, xml_string, charset=None):
- #return _parse_xml_string(x, charset)
- return _parse_xml_string(xml_string, charset)
- ...
修改后,例子可以正常运行,这么明显的错误都有,果然是2.0beta版
用rpclib实现soap server
文档:http://arskom.github.com/rpclib/
rpclib服务器端接收对象参数
一个简单例子的实现
SERVER
- import logging
- from rpclib.application import Application
- from rpclib.decorator import srpc
- from rpclib.interface.wsdl import Wsdl11
- from rpclib.protocol.soap import Soap11
- from rpclib.service import ServiceBase
- from rpclib.model.complex import Iterable
- from rpclib.model.primitive import Integer
- from rpclib.model.primitive import String
- from rpclib.server.wsgi import WsgiApplication
- from rpclib.util.simple import wsgi_soap11_application
- class HelloWorldService(ServiceBase):
- @srpc(String, Integer, _returns=Iterable(String))
- def say_hello(name, times):
- '''''
- Docstrings for service methods appear as documentation in the wsdl
- <b>what fun</b>
- @param name the name to say hello to
- @param the number of times to say hello
- @return the completed array
- '''
- print times
- for i in xrange(times):
- yield u'Hello, %s' % name
- if __name__=='__main__':
- try:
- from wsgiref.simple_server import make_server
- except ImportError:
- print "Error: example server code requires Python >= 2.5"
- logging.basicConfig(level=logging.DEBUG)
- logging.getLogger('rpclib.protocol.xml').setLevel(logging.DEBUG)
- application = Application([HelloWorldService], 'rpclib.examples.hello.soap', interface=Wsdl11(), in_protocol=Soap11(), out_protocol=Soap11())
- server = make_server('192.168.0.31', 7789, WsgiApplication(application))
- print "listening to http://192.168.0.31:7789"
- print "wsdl is at: http://192.168.0.31:7789/?wsdl"
- server.serve_forever()
Client
- from suds.client import Client
- c = Client('http://192.168.0.31:7789/?wsdl')
- a = c.service.say_hello(u'punk', 5)
- print a