There's a problem with reloading modules or in general with dealing with Python classes in long-running systems. You can reload the module, recreate the class, but all the old instances are still out there. What to do? Bind classes tightly to their names, turn (re)creation of a class in to modification of the old class. What better than a metaclass:
registry = {}
class Reloadable(type):
def __new__(me, className, bases, d):
moduleName = d['__module__']
try:
current = registry[moduleName][className]
except KeyError:
current = None
if current:
regenerateClass(current, bases, d)
return current
cls = type.__new__(me, className, bases, d)
registry.setdefault(moduleName, {})[className] = cls
return cls
def regenerateClass(current, bases, d):
#print "Reloading class %s" % current
for name in current.__dict__.keys():
if name in ['__name__', '__metaclass__',
'__module__', '__dict__',
'__weakref__', '__bases__']:
continue
delattr(current, name)
for name, value in d.items():
setattr(current, name, value)
# Hmm... fails:
# current.__bases__ = bases
return current
if __name__ == '__main__':
class C(object):
__metaclass__ = Reloadable
def test(self):
print 'first'
c = C()
c.test()
class C(object):
__metaclass__ = Reloadable
def test(self):
print 'second'
c.test()
I'm not sure how to handle a class whose inheritance changes --
__bases__ seems resistent to change. And who knows what else is
flawed here; this is totally off the top of my head. But there are some
compelling aspects to this.
I've put this in the Webware Sandbox, Sandbox/ianbicking/misc/Reloadable.py
Hmm, this looks familiar... have you seen my Python Cookbook recipe that does more-or-less the same thing?
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/160164
You can't (realistically) do anything about __bases__ in 2.2.X. You can in 2.3 because I wrote __bases__ changing code to support exactly this...