Welcome, guest | Sign In | My Account | Store | Cart

This recipe shows how to build an xmlrpc multithread server that exposes a COM component as a web service.

Python, 71 lines
 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# a python COM object (it's a standard sample, I've reported it here only 
# to let the recipe be complete (file testcomserver.py).

##################################################
class HelloWorld:
    _reg_clsid_ = "{7CC9F362-486D-11D1-BB48-0000E838A65F}"
    _reg_desc_ = "Python Test COM Server"
    _reg_progid_ = "Python.TestServer"
    # Next line assumes file is "testcomserver.py"
    _reg_class_spec_ = "testcomserver.HelloWorld"
    _public_methods_ = ['Hello']
    _public_attrs_ = ['softspace', 'noCalls']
    _readonly_attrs_ = ['noCalls']
    
    def __init__(self):
        self.softspace = 1
        self.noCalls = 0
    def Hello(self, who):
        self.noCalls = self.noCalls + 1
        # insert "softspace" number of spaces
        return "Hello" + " " * self.softspace + str(who)

if __name__=='__main__':
    import win32com.server.register
    win32com.server.register.UseCommandLine(HelloWorld)
##################################################
##################################################

##################################################
# the CherryPy (v.0.10) server definition file (file testXmlRpc.cpy)
def initProgram():
    import win32com.client, pythoncom, time

def initThread(threadIndex):
    time.sleep(threadIndex * 0.2)
    # start the COM environment in a MT situation
    pythoncom.CoInitialize()
    # dispatch a COM object to each thread via "request" reserved variable
    request.x=win32com.client.Dispatch("Python.TestServer")


CherryClass Xml_rpc:

view:
    def hello(self, a) xmlrpc:
        # Return the COM hello method
        return request.x.hello(a)
    def nocalls(self) xmlrpc:
        # Return the COM noCalls variable
        return request.x.noCalls
##################################################
##################################################

##################################################
# the CherryPy server configuration file (file testXmlRpcServer.cfg)
[server]
typeOfRequests=xmlRpc,web
threadPool=3
##################################################
##################################################

##################################################
# a client test program 
import xmlrpclib, time
if __name__=='__main__':
    testsvr = xmlrpclib.Server("http://127.0.0.1:8000")
    print testsvr.xml.rpc.hello("I love cherry pie " + str(x))
    print testsvr.xml.rpc.nocalls()
    raw_input("press a key:...")
##################################################
##################################################

It's a standard problem to be able to invoke a legacy COM component from a web application: this is an application of the "remote facade" patter to this issue. All the magic is in the initThread(threadIndex) method: here we had to be sure there's a distinct COM object for each server thread, in order to avoid collision in its usage. The CherryPy xmlrpc methods are simply wrappers for COM-exposed entities.

As reference search google for "python win32com CoInitialize" and "cherrypy thread pool".

Created by gian paolo ciceri on Mon, 22 Nov 2004 (PSF)
Python recipes (4591)
gian paolo ciceri's recipes (7)

Required Modules

  • (none specified)

Other Information and Tasks