Reload Tricks

K

Kamilche

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
 
M

Michael Spencer

Kamilche said:
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: ... pass
... ... pass
... ... pass
...Traceback (most recent call last):
Traceback (most recent call last):

An alternative approach (with some pros and cons) is to modify the class in
place, using something like:
... """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)
... ... attr = "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
 
K

Kamilche

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
 
K

Kamilche

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

Alex Martelli

Kamilche said:
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
 
M

Michael Spencer

Kamilche said:
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 said:
An alternative approach (with some pros and cons) is to modify the class in place, using something like:

... """Updates attributes of cls to match those of to_cls"""
...
... DONOTCOPY = ("__name__","__bases__","__base__",
... "__dict__", "__doc__","__weakref__")
etc...
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/Cookbook/Python/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
 
K

Kamilche

Well, I look forward to seeing the new version. I have the old version
of the Python cookbook, it was very useful!
 
A

Alex Martelli

Kamilche said:
Well, I look forward to seeing the new version. I have the old version
of the Python cookbook, it was very useful!

I hope the new one is even better -- many more recipes, all updated to
Python 2.3 and 2.4. The old one will remain useful for all those who
need to keep using older versions of Python, though; to fit more recipes
in, the historical discussions of how you did things with Python 1.5.2,
1.6, 2.0 etc have been ruthlessly snipped...


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top