>>> import sys, math
>>> reload(math)
<module 'math' (built-in)>
>>> sys.modules.pop('math')
<module 'math' (built-in)>
>>> __import__('math')
<module 'math' (built-in)>
>>> reload(math)
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
reload(math)
ImportError: reload(): module math not in sys.modules
>>> sys.modules.get('math')
<module 'math' (built-in)>
>>> id(math), id(sys.modules.get('math'))
(45429424, 45540272)
函数 __import__ 会在import声明中被调用。import导入一个模块分两步:
find a module, and initialize it if necessary;
define a name or names in the local namespace;
其中第一步有以下的搜寻过程:a): sys.modules; b): sys.meta_path; c):sys.path_hooks, sys.path_importer_cache, and sys.path
G:CnblogsAlpha Panda>python Reloader.py
This is Foo member func bar, self.cur_mod = hotfix
hotfix gl_var = 0
This is Foo member func bar, self.cur_mod = hotfix
hotfix gl_var = 0
This is Foo member func bar, self.cur_mod = __main__
####### 修改hotfix.Foo.bar函数的定义 #######
1
After Modified! This is Foo member func bar, self.cur_mod = hotfix
hotfix gl_var = 0
This is Foo member func bar, self.cur_mod = __main__
View Code
上面的结果说明修改hotfix.Foo.bar的定义并reload之后,新定义的函数对于新建的对象是生效的,但是对于已经存在的对象reloader.foo并不生效。下面添加函数替换:
1 import hotfix
2
3 def reload_with_func_replace():
4 old_cls = hotfix.Foo
5 reload(hotfix)
6 for name, value in hotfix.Foo.__dict__.iteritems():
7 if inspect.isfunction(value) and name not in ('__init__'):
8 # setattr(foo.bar, 'func_code', hotfix.Foo.bar.func_code)
9 old_func = old_cls.__dict__[name]
10 setattr(old_func, "func_code", value.func_code)
11 setattr(hotfix, 'Foo', old_cls)
12
13 if __name__ == '__main__':
14 foo = hotfix.Foo()
15 foo.cur_mod = __name__
16 cmd = 1
17 while 1 == cmd:
18 reload_with_func_replace()
19 foo.bar()
20 cmd = input()
看一下测试结果:
G:CnblogsAlpha Panda>python Reloader.py
This is Foo member func bar, self.cur_mod = hotfix
hotfix gl_var = 0
This is Foo member func bar, self.cur_mod = hotfix
hotfix gl_var = 0
This is Foo member func bar, self.cur_mod = __main__
1
After Modified! This is Foo member func bar, self.cur_mod = hotfix
hotfix gl_var = 0
After Modified! This is Foo member func bar, self.cur_mod = __main__
View Code
在没有重新创建reloader模块中的对象foo的情况下,被修改后的函数代码被执行了,而且对象的状态(self.cur_mod)被保留下来了。