def OldFunc():
a = 1
print("OldFunc a: {0}".format(a))
测试文件 test_func.py
如果要修改函数OldFunc功能一般是直接修改文件
然后reload(test_func)
出现问题:若有文件runc.py是这样导入OldFunc,
form test_func import OldFunc
OldFunc()
则run.py 的OldFunc()调用还是旧的
此时,还要执行reload(runc),去更新OldFunc函数
如果有大量的文件对热更函数进行了 from xxx import func
则要跟新所有函数实属麻烦
解决方法:替换函数的__code__
测试函数文件 test_func.py:
def OldFunc():
a = 1
print("OldFunc a: {0}".format(a))
def NewFunc():
a = 2
print("NewFunc a: {0}".format(a))
执行run.py:
def _update_function(oldfunc, newfunc):
oldfunc.__doc__ = newfunc.__doc__
oldfunc.__dict__.update(newfunc.__dict__)
if hasattr(newfunc, "__code__"):
attr_name = "__code__"
else:
attr_name = 'func_code'
old_code = getattr(oldfunc, attr_name)
new_code = getattr(newfunc, attr_name)
if not code_objects_equal(old_code, new_code):
setattr(oldfunc, attr_name, new_code)
try:
oldfunc.__defaults__ = newfunc.__defaults__
except AttributeError:
oldfunc.func_defaults = newfunc.func_defaults
return oldfunc
import test_func
from test_func import *
if __name__ == "__main__":
OldFunc()
_update_function(test_func.OldFunc, test_func.NewFunc)
OldFunc()
结果:
OldFunc a: 1
NewFunc a: 2
更新类方法、类函数、静态函数、普通函数等实现
# -*- coding: gbk -*-
import types
import imp
def code_objects_equal(code0, code1):
for d in dir(code0):
if d.startswith('_') or 'lineno' in d:
continue
if getattr(code0, d) != getattr(code1, d):
return False
return True
def _update_function(oldfunc, newfunc):
oldfunc.__doc__ = newfunc.__doc__
oldfunc.__dict__.update(newfunc.__dict__)
if hasattr(newfunc, "__code__"):
attr_name = "__code__"
else:
attr_name = 'func_code'
old_code = getattr(oldfunc, attr_name)
new_code = getattr(newfunc, attr_name)
if not code_objects_equal(old_code, new_code):
setattr(oldfunc, attr_name, new_code)
try:
oldfunc.__defaults__ = newfunc.__defaults__
except AttributeError:
oldfunc.func_defaults = newfunc.func_defaults
return oldfunc
def _update_method(oldmeth, newmeth):
if hasattr(oldmeth, 'im_func') and hasattr(newmeth, 'im_func'):
update(oldmeth.im_func, newmeth.im_func)
elif hasattr(oldmeth, '__func__') and hasattr(newmeth, '__func__'):
update(oldmeth.__func__, newmeth.__func__)
return oldmeth
def _update_classmethod(oldcm, newcm):
update(oldcm.__get__(0), newcm.__get__(0))
def _update_staticmethod(oldsm, newsm):
update(oldsm.__get__(0), newsm.__get__(0))
def update(oldob, newob):
if not isinstance(oldob, type(newob)):
# update error not same type
return oldob
if isinstance(newob, types.FunctionType):
_update_function(oldob, newob)
elif isinstance(newob, types.MethodType):
_update_method(oldob, newob)
elif isinstance(newob, classmethod):
_update_classmethod(oldob, newob)
elif isinstance(newob, staticmethod):
_update_staticmethod(oldob, newob)
return oldob