Python中的Doctest和装饰器
我在尝试用Python的装饰器来捕捉异常并记录这些异常。
import os.path
import shutil
class log(object):
def __init__(self, f):
print "Inside __init__()"
self.f = f
def __call__(self, *args):
print "Inside __call__()"
try:
self.f(*args)
except Exception:
print "Sorry"
@log
def testit(a, b, c):
print a,b,c
raise RuntimeError()
if __name__ == "__main__":
testit(1,2,3)
这样做效果很好。
Desktop> python deco.py
Inside __init__()
Inside __call__()
1 2 3
Sorry
但问题是,当我想用doctest来测试的时候,
@log
def testit(a, b, c):
"""
>>> testit(1,2,3)
"""
print a,b,c
raise RuntimeError()
if __name__ == "__main__":
import doctest
doctest.testmod()
似乎什么都没有发生。
Desktop> python deco2.py
Inside __init__()
这是什么原因呢?
2 个回答
6
你需要把文档字符串复制到你的装饰器里:
class log(object):
def __init__(self, f):
print "Inside __init__()"
self.f = f
self.__doc__ = f.__doc__
def __call__(self, *args):
print "Inside __call__()"
try:
self.f(*args)
except Exception:
print "Sorry"
这个装饰器会“替代”被装饰的函数,只有通过复制文档字符串,其他人才能看到这个属性。
你可以使用 functools.update_wrapper()
来帮你复制文档字符串,还有其他一些属性:
from functools import update_wrapper
class log(object):
def __init__(self, f):
print "Inside __init__()"
self.f = f
update_wrapper(self, f)
def __call__(self, *args):
print "Inside __call__()"
try:
self.f(*args)
except Exception:
print "Sorry"
9
被装饰的函数(其实是一个类的实例)并没有继承原始函数的 __doc__
属性(这是 doctest
解析的内容)。你可以选择把 __doc__
属性复制到这个类的实例上,但……老实说,我觉得这里根本不需要用到类,直接使用 functools.wraps
可能会更好。
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args):
try:
return func(*args)
except Exception:
print "sorry"
return wrapper