用“with”编写python装饰器

时间:2013-09-29 17:49:52

标签: python

我正在尝试编写一个可以与with关键字一起使用的装饰器。

# regular code ...
with my_exception_handler():
    # dangerous code ...
# regular code ...

并且my_exception_handler将接收一个函数并将其包装在一个巨大的try-except。

我想让它成为一个装饰器/包装器,因为它是很多我不想复制粘贴的代码。我无法弄清楚从哪里开始。我写了一个普通的装饰器,它适用于函数,但不适用于中间代码块。

3 个答案:

答案 0 :(得分:5)

你与with一起使用的东西是一个上下文管理器而不是一个装饰器 - 这两个是完全不同的东西。

编辑:请参阅kindall的帖子,了解如何编写简单的上下文管理器,而不必使用完整的类;我没有时间用这样的例子修改我的答案:)

答案 1 :(得分:2)

您需要编写上下文管理器,而不是装饰器。您可以使用contextlib.contextmanager装饰器轻松完成您想要的操作。

from contextlib import contextmanager

@contextmanager
def my_exception_handler():
     try:
         yield          # execute the code in the "with" block
     except Exception as e:
         # your exception-handling code goes here
         print e

# try it out
with my_exception_handler():
    raise ValueError("this error has value")

答案 2 :(得分:0)

在了解了上下文管理器之后,我采用了extended traceback function并将其转换为装饰器和上下文管理器,其中包含以下几个片段:

def traceback_decorator(function):

    def wrap(*args, **kwargs):

        try:
            return function(*args, **kwargs)
        except:
            print_exc_plus()


def traceback_wrapper(function=None, *args, **kwargs):

    context = _TracebackContext()

    if function is None:
        return context

    with context:
        function(*args, **kwargs)

class _TracebackContext(object):

    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type:
            print_exc_plus()