Python中的Doctest和decorator

Python中的Doctest和decorator,python,decorator,python-decorators,doctest,Python,Decorator,Python Decorators,Doctest,我试图使用Python decorator捕获异常并记录异常 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:

我试图使用Python decorator捕获异常并记录异常

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__()

这个怎么了

您需要将文档字符串复制到装饰器:

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"
decorator替换修饰函数,并且只有通过在docstring上复制,该属性才对任何人可见

您可以利用此处为您复制docstring以及其他几个属性:

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"
修饰后的函数(实际上是一个类实例)没有获得原始函数的
\uuuuu doc\uuuu
属性(这是
doctest
解析的内容)。您可以将
\uuuuu doc\uuuuu
复制到类实例,但是。。。老实说,我根本不认为有必要在这里创建一个类——您最好只使用
functools.wrapps

import functools
def log(func):
    @functools.wraps(func)
    def wrapper(*args):
        try:
            return func(*args)
        except Exception:
            print "sorry"
    return wrapper

对此没有帮助?@metatoaster:
functools.wrapps()
(和
functools.update_wrapper()
)专门针对函数。实现后,它也可以在类上工作<代码>包装(f)(自我)在那里就可以了。