By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,986 Members | 1,583 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,986 IT Pros & Developers. It's quick & easy.

Reload Tricks

P: n/a
I want my program to be able to reload its code dynamically. I have a
large hierarchy of objects in memory. The inheritance hierarchy of
these objects are scattered over several files.

I find that after reloading the appropriate files, and overwriting the
__class__ of object instances, one more thing is necessary: reloading
the __bases__ of each reloaded class. If I don't do this, the modules
reloaded first point to old versions of the classes from later modules,
and when the later module is reloaded, it doesn't update the
inheritance hierarchy of classes already loaded.

This appears to be working... but now I'm wondering, what else did it
not change? Can I expect more toes to be blown off?

--Kamilche

Jul 18 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Kamilche wrote:
I want my program to be able to reload its code dynamically. I have a
large hierarchy of objects in memory. The inheritance hierarchy of
these objects are scattered over several files.

I find that after reloading the appropriate files, and overwriting the
__class__ of object instances, one more thing is necessary: reloading
the __bases__ of each reloaded class. If I don't do this, the modules
reloaded first point to old versions of the classes from later modules,
and when the later module is reloaded, it doesn't update the
inheritance hierarchy of classes already loaded.

This appears to be working... but now I'm wondering, what else did it
not change? Can I expect more toes to be blown off?

--Kamilche


There are some cases when re-assigning __class__ isn't possible, for example:
class A(object): ... pass
... class B(dict): ... pass
... class C: ... pass
... a = A()
a.__class__ = B Traceback (most recent call last):
File "<input>", line 1, in ?
TypeError: __class__ assignment: 'A' object layout differs from 'B' a.__class__ = C Traceback (most recent call last):
File "<input>", line 1, in ?
TypeError: __class__ must be set to new-style class, not 'classobj' object
An alternative approach (with some pros and cons) is to modify the class in
place, using something like:
def reclass(cls, to_cls): ... """Updates attributes of cls to match those of to_cls"""
...
... DONOTCOPY = ("__name__","__bases__","__base__",
... "__dict__", "__doc__","__weakref__")
...
... fromdict = cls.__dict__
... todict = to_cls.__dict__
...
... # Delete any attribute present in the new class
... [delattr(cls,attr) for attr in fromdict.keys()
... if not((attr in todict) or (attr in DONOTCOPY)) ]
...
... for to_attr, to_obj in todict.iteritems():
...
... if to_attr in DONOTCOPY:
... continue
...
... # This overwrites all functions, even if they haven't changed.
... if type(to_obj) is types.MethodType:
... func = to_obj.im_func
... to_obj = types.MethodType(func,None, cls)
...
... setattr(cls, to_attr,to_obj)
... class A(object): ... attr = "A"
... class B(object): ... attr = "B"
... a = A()
reclass(A,B)
a.attr 'B'


This copies attributes of old and new-style classes (in fact anything with a
__dict__ so probably a module would work too)

You still run into problems trying to re-assigning __bases__ to incompatible
objects, but this one-attribute-at-a-time approach gives you the potential to
intercept problem cases. In the example above, problems are avoided by not
copying __bases__.

An additional advantage of this aprpoach is that you don't need to keep track of
class instances, in order to change their __class__. Instances automatically
acquire the new behavior

One wart is that class docstrings are not writeable, so cannot be copied. Why?

Michael

Jul 18 '05 #2

P: n/a
That's a powerful advantage - not having to track class instances.
Thanks for the tip! I just got done doing it 'my way' though, now I'll
have to change it. It took me all day! :-D

Jul 18 '05 #3

P: n/a
Would it be possible to just not copy any attribute that starts and
ends with '__'? Or are there some important attributes being copied?

Jul 18 '05 #4

P: n/a
Kamilche <kl*******@comcast.net> wrote:
I want my program to be able to reload its code dynamically. I have a
large hierarchy of objects in memory. The inheritance hierarchy of
these objects are scattered over several files.


Michael Hudson has a nice custom metaclass for that in Activestate's
online cookbook -- I made some enhancements to it as I edited it for the
forthcoming 2nd edition of the cookbook (due out in a couple of months),
but the key ideas are in the online version too (sorry, no URL at hand).
Alex
Jul 18 '05 #5

P: n/a
Kamilche wrote:
I want my program to be able to reload its code dynamically. I have a
large hierarchy of objects in memory. The inheritance hierarchy of
these objects are scattered over several files.
Michael Spencer wrote: An alternative approach (with some pros and cons) is to modify the class in place, using something like:
>>> def reclass(cls, to_cls):
... """Updates attributes of cls to match those of to_cls"""
...
... DONOTCOPY = ("__name__","__bases__","__base__",
... "__dict__", "__doc__","__weakref__")

etc...

Kamilche wrote: Would it be possible to just not copy any attribute that starts and
ends with '__'? Or are there some important attributes being copied?

Possible? of course, it's Python ;-)

But there are many 'magic' attributes for behavior that you probably do want to
copy:

e.g., __getitem__, __setitem__ etc...

See: http://docs.python.org/ref/specialnames.html

Michael Hudson's recipe:
http://aspn.activestate.com/ASPN/Coo.../Recipe/160164
does auto-reloading "automatically", at the price of changing the type of the
classes you want to manage. It's a very convenient approach for interactive
development (which is the recipe's stated purpose). It works by tracking
instances and automatically updating their class. If your program relies on
class identity, you may run into problems.
Michael
Jul 18 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.