包装函数和协同程序的条件收益率

时间:2018-02-16 17:53:19

标签: python-3.x python-decorators coroutine

是否有规范的方法来修饰函数和协同程序?

def timed(func):
    """
    A decorator for logging the execution time of each function decorated with it.

    :param func: function to be wrapped
    :return: a decorated function (in __debug__ mode) or the function is untouched.
    """
    if not __debug__:
        return func

    name = func.__name__
    logger = logging.getLogger("timer")
    logger.addHandler(logging.StreamHandler())
    logger.setLevel(logging.DEBUG)
    is_coro = asyncio.iscoroutinefunction(func)
    wrapper = asyncio.coroutine if is_coro else lambda f: f

    @functools.wraps(func)
    @wrapper
    def wrapped(*args, **kwargs):
        start = time.time()
        try:
            val = func(*args, **kwargs)
            # if is_coro:
            #     yield from val
        except Exception as e:
            logger.debug("{} failed in {:.05}s".format(name, time.time() - start))
            raise e
        else:
            logger.debug("{} ran in {:.05}s".format(name, time.time() - start))
            return val
    return wrapped

当然,注释掉的行会将wrapped函数更改为生成器,无论asyncio.coroutine是否用作装饰器。

除了将其分成两个不同的函数之外,还有更好的方法吗?

def timed(func):
    """
    A decorator for logging the execution time of each function decorated with it.

    :param func: function to be wrapped
    :return: a decorated function (in __debug__ mode) or the function is untouched.
    """
    if not __debug__:
        return func

    name = func.__name__
    logger = logging.getLogger("timer")
    logger.addHandler(logging.StreamHandler())
    logger.setLevel(logging.DEBUG)
    is_coro = asyncio.iscoroutinefunction(func)

    @functools.wraps(func)
    def wrapped(*args, **kwargs):
        start = time.time()
        try:
            val = func(*args, **kwargs)
        except Exception as e:
            logger.debug("{} failed in {:.05}s".format(name, time.time() - start))
            raise e
        else:
            logger.debug("{} ran in {:.05}s".format(name, time.time() - start))
            return val

    @functools.wraps(func)
    async def wrapped_async(*args, **kwargs):
        start = time.time()
        try:
            val = await func(*args, **kwargs)
        except Exception as e:
            logger.debug("{} failed in {:.05}s".format(name, time.time() - start))
            raise e
        else:
            logger.debug("{} ran in {:.05}s".format(name, time.time() - start))
            return val

    return wrapped_async if is_coro else wrapped

0 个答案:

没有答案