Neil Schemenauer wrote: > On Sat, Dec 06, 2003 at 01:18:38AM -0500, Graham Fawcett wrote: > >>Attached is a utility module that lets you "wrap" a PTL module in a proxy >>that will reload itself automatically if the source file changes. > > > If you use 'from ... import ...' then just reloading the module > doesn't work too well. This is what I have been using: The 'from package import module' form should work fine with my approach; but it definitely wouldn't handle 'from package.module import ClassDefinition' forms. In hindsight, I shouldn't have called my code a "reloader" since it doesn't actually use the reload() mechanism. It just compiles a source file into a code object, exec()'s the code object in a mostly-empty dictionary and returns it as an "anonymous pseudo-module". It's not even a module instance; it's a dictionary proxied by an object. But Quixote only needs a namespace, not a module, so it works OK. It also doesn't try to be global; the reloadable module is only reloaded from the point of view of any importer which declares it as reloadable(!). Assume that modules A and B both import module C, but only A uses "import C; C = ReloadableModule(C)". If the source for C is modified, then A.C will refer to the new code, but B.C will continue to refer to the old version. I don't consider this scary or magical, since the behaviour is explicit. For the kind of development (and debugging) I'm doing, I find this satisfactory; most of my PTL modules are only imported from one parent anyway, or I'm only debugging them from one POV at a time. I wouldn't use this approach for any module declaring classes of any objects that persisted beyond a single request. Then again, I probably wouldn't use reload() in that case, either. ;-) But it seems to work nicely for PTL modules and UI classes that define throwaway objects. > > def reload_module(fullname): > module = sys.modules[fullname] > old_items = module.__dict__.items() > reload(module) > objects = {} # [(old_id, new_object)] > for name, value in old_items: > if name in module.__dict__: > if name.startswith('_'): > continue > new_value = module.__dict__[name] > if new_value is not value: > objects[id(value)] = new_value > for module in sys.modules.values(): > if not hasattr(module, '__dict__'): > continue > for name, value in module.__dict__.items(): > if id(value) in objects: > print 'updating', getattr(module, '__name__'), name > setattr(module, name, objects[id(value)]) > objects.clear() > > To use it, I created a form that takes 'fullname' as a query string. > I have my editor configured to that hitting a key causing the module > I'm currently editing to be reloaded. It's not perfect but seems to > work okay. Clever approach; certainly more general than mine, since you can reload any module at any time. Best wishes, -- Graham > Neil