有时,比如写RF的测试库的时候,很多方法都写在一个类里。我们又可能需要一个通用的装饰器,比如,要给某个底层类的方法打桩,查看入参和出参,用以理解业务;或者要hold住所有的执行错误,打印堆栈又不想程序退出或用例直接失败
比如捕捉错误的装饰器
import traceback
from functools import wraps
def trier(soft=False):
'''
:param bool soft: 为True时,打印报错堆栈并忽略异常。默认False,打印报错堆栈并抛出异常
:return:
如果要给类方法、静态方法装饰,则该装饰器必须处于比@staticmethod装饰器更内一层才行
'''
def realTrier(func):
'''
:param function func:
:return:
'''
@wraps(func) # 保留__name__ __doc__ __module__
def innerfunc(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception, e:
try:
print(traceback.format_exc())
except:
print e
if not soft:
raise
return innerfunc
return realTrier
或者参数跟踪的装饰器
def tracer(func):
def infunc(*args, **kwargs):
print func.__name__, args, kwargs
res=infunc(*args, **kwargs)
print func.__name__, res
return res
这类装饰器经常会给类里的每个函数都使用
每次都装饰的话,也挺麻烦
python里可以给类写个装饰器,所以可以输入一个类,返回一个新类,这个新类拥有原来类里的所有方法,但所有方法都被装饰
使用元类,可以做到这一点。
目前可以批量装饰普通方法、静态方法、类方法、属性,暂不支持__init__和__del__之类的特殊方法,以免出现意外的问题。
目前类B使用了全局装饰器,假如类B继承自类A,类C继承自类B
则类B、类C内的所有方法都被全局装饰(全局装饰可以被继承)
且类B继承自类A的所有方法也会被全局装饰
但这种装饰不会影响到类A,调用类A下的方法时,所有方法都不被装饰
经过多次尝试,最后的实现代码如下
# clswrapper.py
def skipper(func):
'''
:param function func:
:return:
'''
func.__funskip__=True
return func
def classWrapper(commonDecoratorFunc):
def innerMata(inClass):
def collect_attrib(key, value, new_attrs):
if hasattr(value, '__funskip__'):
new_attrs[key] = value
return
if hasattr(value, '__func__') or isinstance(value