Python: try/except语句的装饰器/包装器



我有一些需要用函数包装的代码块。

try:
    if config.DEVELOPMENT == True:
        # do_some_stuff
except:
    logger.info("Config is not set for development")

然后我再做一次:

try:
    if config.DEVELOPMENT == True:
        # do_some_another_stuff
except:
    logger.info("Config is not set for development")

那么,我如何包装这个"do_some_stuff"one_answers"do_some_another_stuff"呢?

我想用contextmanager写函数:

@contextmanager
def try_dev_config(name):
    try:
        if name is not None:
            yield
    except Exception as e:
        print "not dev config"
with try_dev_config("config.DEVELOPMENT"):
    # do_some_stuff

我得到了一个错误:

RuntimeError: generator didn't yield

你可以传入一个函数

boolean = True
def pass_this_in():
    print("I just did some stuff")
def the_try_except_bit(function):
    try:
        if boolean:
            function()
    except:
        print("Excepted")

# Calling the above code
the_try_except_bit(pass_this_in)

如果你想减少"pass_this_in"定义位,那么你可以使用lambda函数定义:

pass_this_in = lambda : print("I just did some stuff")

我不确定上下文管理器是实现您想要的效果的好方法。上下文管理器的目标是提供一种机制来打开/实例化资源,允许(或不允许)访问它,并在您不再需要它时自动关闭/清除它。

恕我直言,你需要的是一个装饰师。装饰器旨在围绕函数调用执行代码。它会迫使你把每个代码块放在一个函数中,但我不认为这很难。你可以这样实现它:

class Config(object):
    """for demonstration purpose only: used to have a config.DEVELOPMENT value"""
    DEVELOPMENT = True
class Logger(object):
    """for demonstration purpose only: used to have a logger.info method"""
    @staticmethod
    def info(msg):
        print("Logged: {}".format(msg))
def check_dev_config(config, logger):
    def dev_config_checker(func):
        def wrapper(*args, **kwargs):
            try:
                if config.DEVELOPMENT:
                    func(*args, **kwargs)
            except Exception as err:
                logger.info(
                    "Config is not set for developpement: {}".format(err))
        return wrapper
    return dev_config_checker
@check_dev_config(Config, Logger)
def do_stuff_1():
    print("stuff 1 done")
@check_dev_config(Config, Logger)
def do_stuff_2():
    raise Exception("stuff 2 failed")
do_stuff_1()
do_stuff_2()

这段代码打印

stuff 1 done
Logged: Config is not set for developpement: stuff 2 failed

解释:

  • check_dev_config函数实际上是一个装饰生成器,它接受configlogger作为参数。
  • 它返回dev_config_checker函数,这是一个实际的(参数化的)装饰器,并接受一个函数作为参数来装饰。
  • 这个装饰器返回一个wrapper函数,它实际上会围绕被装饰函数调用运行代码。在这个函数中,只有当config.DEVELOPMENT被求值为True时,才会在try/except结构体中调用修饰函数。在例外情况下,使用logger记录信息。
  • 每个要装饰的代码块都被放入一个函数(do_stuff_1, do_stuff_2)中,并使用check_dev_config装饰生成器进行装饰,给它configlogger
  • 当被装饰的函数被调用时,它们是通过它们的装饰器而不是直接调用的。如您所见,do_stuff_2异常已被捕获,并且消息已被记录。

最新更新