> from m import f > > look for module m in the global cache > if not there, then: > search for m.py > compile it to a Module object > put the Module object in the cache > look for object named "f" in the Module object agree
> create a new name "f" in the local namespace > set the name "f" to cached object strongly agree > The important thing to notice is the the name "f" is a local variable. It > doesn't, and can't, remember that it comes from module m. Reloading m > can't do anything to f, because the connection is lost. disagree with 2nd stmt. local 'f' does *remember* (if that's the right word) where it comes from, because it points to the original obj, as you said: 'set the name "f" to cached object' py0.py ====== def f(): ... >>> from py0 import * >>> assert f.__module__ == sys.modules['py0'].__name__ >>> assert f.__globals__ is sys.modules['py0'].__dict__ > Now consider that the object "f" that came from m was itself imported > from another module, "service". Reloading service doesn't help, because > m.f doesn't know it came from service. Reloading m doesn't help, because > all that does is run "from service import f" again, and that just fetches > f from the global cache. disagree with 2nd stmt, partially disagree with 3rd stmt reloading 'service' partially helps, since it updates the mod obj pointed by 'service' in global cache. it needs to be followed by reloading m, then we have m.f points to the new obj. the important part is the order of reloading mods l.py ==== def f(): ... m.py ==== from l import * >>> from m import * at this point, the func obj is referenced by 3 distinct variables with name 'm'(one in each mod) >>> assert sys.getrefcount(f) == 4 >>> referrers = gc.get_referrers(f) >>> mod_dicts = [sys.modules[k].__dict__ for k in sys.modules if k == 'l' or k >>> == 'm' or k == __name__] >>> for d in mod_dicts: ... referrers.remove(d) >>> assert len(referrers) == 0 >>> imp.reload(sys.modules['l']) now the original func obj is ref'ed by 2 vars, the new func obj is ref'ed by 1 var >>> imp.reload(sys.modules['m']) >>> f = sys.modules['m'].f now the original func obj is ready to be recollected, the new func obj is ref'ed by 3 vars > The simplest, easiest way of dealing with this is not to have to deal > with it: don't use "from service import f", and ESPECIALLY don't use > "from service import *". Always use fully-qualified importing: > > import service > service.f strongly agree > The other way is not to bother with reload. It's not very powerful, only > good for the simplest use in the interactive interpreter. Just exit the > interpreter and restart it. set, del, reload are useful when it comes to structure manipulation at runtime, most langs differentiate it, labeling as metaprogramming, py smashes the diff in an elegant way (oh flattery, i love it) ;) as their names say, set & del only bind & unbind obj to var, the obj to bind must be in its bytecode form, in theory one could do it, maybe thru modules that are categorized as "Python Language Services" in the lib manual, but it's not practical (e.g. see the last stmt of types.CodeType.__doc__). this is where 'reload' steps in, and so the story goes ... -- http://mail.python.org/mailman/listinfo/python-list