python热更优化,替换__code__方式

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值