I have an XMLserver that uses the method
SimpleXMLRPCServer.register_instance to register a class and it's methods. Something like:
....
inst = ServiceClass(init_params)
server.register_instance(inst)
server.register_introspection_functions()
try:
server.serve_forever()
finally:
server.server_close()
The serviceclass looks like:
class ServiceClass(object):
"""ServiceClass calls the xxxx executable and returns stdout & stderr"""
def __init__(self, params):
super(ServiceClass, self).__init__()
self.params = params
print "Init with %s" % self.params
def _shell_exec(self, cmd=[]):
.......
....
...
def dbupdate(self, sometext=""):
"""Given an object, try call the xxxx binary and
return the output of the command
Keyword arguments:
params:
sometext -- text of the object
"""
if not len('sometext'):
raise MissingObjectError("No text passed for command")
# Create a tempfile
(tmpfd, fname) = tempfile.mkstemp()
os.write(tmpfd, sometext)
os.close(tmpfd)
# Execute
cmd_exe = self.params['cmd']
cmd_exe.extend([fname])
ret_stdout, ret_stderr = self._shell_exec(cmd_exe)
# Cleanup file
os.unlink(fname)
print "cmd: %s\nself.cmd: %s\nfname: %s\n" %(cmd_exe, self.params['cmd'], fname)
return (ret_stdout, ret_stderr)
Turns out that python keeps state since... the instance is created only once at server startup. All subsequent calls share this instance. And that affects the class variables. Notice that tempfiles from a prior run are visible to a later run which might be from a different client. :(
:!python some_webservice_xmlrpc.py -d 1 -p 8000
Listening on :8000...
Service URI is http://:8000/
Use Control-C to exit
CMD: ['/path/to/executable', '-c', '/path/to/config.conf', '-f', '/tmp/tmpkCXRS-']
cmd: ['/path/to/executable', '-c', '/path/to/config.conf', '-f', '/tmp/tmpkCXRS-']
self.cmd: ['/path/to/executable', '-c', '/path/to/config.conf', '-f', '/tmp/tmpkCXRS-']
fname: /tmp/tmpkCXRS-
machine1.example.net - - [21/Apr/2011 14:53:08] "POST / HTTP/1.0" 200 -
CMD: ['/path/to/executable', '-c', '/path/to/config.conf', '-f', '/tmp/tmpkCXRS-', '/tmp/tmpBGDHHU']
cmd: ['/path/to/executable', '-c', '/path/to/config.conf', '-f', '/tmp/tmpkCXRS-', '/tmp/tmpBGDHHU']
self.cmd: ['/path/to/executable', '-c', '/path/to/config.conf', '-f', '/tmp/tmpkCXRS-', '/tmp/tmpBGDHHU']
I tried different solutions from
del cmd prior to return to initializing all variables to None|"" at the start of the method. Didn't work.. till I remembered
shallow copying. With a deep copy,
....
# cmd_exe.extend([fname])
#Replace with
cmd_exe = copy.deepcopy(self.params['cmd'])
....
things behave as expected:
Listening on :8000...
Service URI is http://:8000/
Use Control-C to exit
Init with {'debug': 1, 'cmd': ['/path/to/executable', '-c', '/path/to/config.conf', '-f']}
CMD: ['/path/to/executable', '-c', '/path/to/config.conf', '-f', '/tmp/tmpLTR0-S']
cmd: ['/path/to/executable', '-c', '/path/to/config.conf', '-f', '/tmp/tmpLTR0-S']
self.cmd: ['/path/to/executable', '-c', '/path/to/config.conf', '-f']
fname: /tmp/tmpLTR0-S
machine1.example.net - - [21/Apr/2011 14:58:19] "POST / HTTP/1.0" 200 -
CMD: ['/path/to/executable', '-c', '/path/to/config.conf', '-f', '/tmp/tmpxdCOtw']
cmd: ['/path/to/executable', '-c', '/path/to/config.conf', '-f', '/tmp/tmpxdCOtw']
self.cmd: ['/path/to/executable', '-c', '/path/to/config.conf', '-f']
fname: /tmp/tmpxdCOtw
machine1.example.net - - [21/Apr/2011 14:58:26] "POST / HTTP/1.0" 200 -
No comments:
Post a Comment