8

We have a wrapper around a suds (SOAP) request, that we use like this throughout our app:

from app.wrapper import ByDesign
bd = ByDesign()

Unfortunately, this instantiation is made at several points per request, causing suds to redownload the WSDL file, and I think we could save some time by making bd = ByDesign() return a singleton.

Since suds is not threadsafe, it'd have to be a singleton per request.

The only catch is, I'd like to make it so I don't have to change any code other than the app.wrapper.ByDesign class, so that I don't have to change any code that calls it. If there wasn't the 'singleton per request' requirement, I'd do something like this:

class ByDesignRenamed(object):
    pass

_BD_INSTANCE = None
def ByDesign():
    global _BD_INSTANCE
    if not _BD_INSTANCE:
       _BD_INSTANCE = ByDesignRenamed()
    return _BD_INSTANCE

But, this won't work in a threaded server environment. Any ideas for me?

synic
  • 25,374
  • 17
  • 102
  • 140
  • I'm not sure, but could you store the instance in the session? The session dictionary should accept any pickleable Python object; that way you could have a singleton per session, so to speak. – miku Jun 04 '11 at 01:12
  • Right, but then I'd have to change all the code accessing it – synic Jun 04 '11 at 01:16
  • It is not pretty, but letting the constructor/call accepting parameters (e.g. a request object) and then check for a valid instance in should be not too difficult from the refactoring side. An other option would be to persist the object somewhere else, memcache, (key-value-)DB or even filesystem. – miku Jun 04 '11 at 01:22

1 Answers1

9

Check out threading.local(), which is somewhere between pure evil and the only way to get things going. It should probably be something like this:

import threading

_local = threading.local()

def ByDesign():
    if 'bd' not in _local.__dict__:
       _local.bd = ByDesignRenamed()
    return _local.bd

Further reading:

Community
  • 1
  • 1
Udi
  • 24,758
  • 8
  • 84
  • 116