简体   繁体   English

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

[英]Python: decorator/wrapper for try/except statement

I have some blocks of code which need to be wrapped by function. 我有一些代码块需要按功能包装。

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

Then I'll do again: 然后我再做一次:

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

So, how can I wrap this "do_some_stuff" and "do_some_another_stuff"? 那么,如何包装这个“ do_some_stuff”和“ do_some_another_stuff”呢?

I'm trying to write function with contextmanager: 我正在尝试使用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

And I got an error: 我得到一个错误:

RuntimeError: generator didn't yield RuntimeError:生成器未产生

You could pass in a function. 您可以传入一个函数。

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)

If you want to reduce the "pass_this_in" definition bit, then you can use lambda function definitions : 如果要减少“ pass_this_in”定义位,则可以使用lambda函数定义

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

I am not sure that a context manager is the good method to achieve what you want. 我不确定上下文管理器是否是实现所需目标的好方法。 The context manager goal is to provide a mecanism to open/instantiate a resource, give access to it (or not) and close/clean it automatically when you no more need it. 上下文管理器的目标是提供一种机制来打开/实例化资源,提供对资源的访问权限(或不授予访问权限)以及在不再需要它时自动关闭/清理资源。

IMHO, what you need is a decorator . 恕我直言,您需要的是一个装饰器 A decorator aims at executing code around a function call. 装饰器旨在围绕函数调用执行代码。 It would force you to put each block of code in a function but I don't think it is so difficult. 这将迫使您将每个代码块放入一个函数中,但我认为这并不那么困难。 You can implement it like this: 您可以这样实现:

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

This code prints 此代码打印

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

Explanations: 说明:

  • The check_dev_config function is actually a decorator generator which accepts the config and the logger as arguments. check_dev_config函数实际上是一个装饰生成器,它接受configlogger作为参数。
  • It returns the dev_config_checker function which is an actual (and parameterised) decorator, and which accepts a function to decorate as argument. 它返回dev_config_checker函数,该函数是实际的(且已参数化的)修饰器,并且接受将其修饰为参数的函数。
  • This decorator returns a wrapper function which will actually run code around the decorated function call. 该装饰器返回一个wrapper函数,该wrapper函数实际上将在装饰后的函数调用周围运行代码。 In this function, the decorated function is called inside a try/except structure and only if the config.DEVELOPMENT is evaluated to True. 在此函数中,仅在config.DEVELOPMENT评估为True的情况下,在try/except结构内部调用修饰函数。 In case of exception, the logger is used to log an information. 在例外情况下, logger用于记录信息。
  • Each block of code to decorate is put into a function ( do_stuff_1 , do_stuff_2 and decorated with the check_dev_config decorator generator, giving it the config and the logger . 每个要装饰的代码块都放入一个函数( do_stuff_1do_stuff_2并用check_dev_config装饰器生成器装饰,为其提供configlogger
  • When decorated functions are called, they are called via their decorator and not directly. 调用装饰函数时,它们是通过装饰器而不是直接调用的。 As you can see, the do_stuff_2 exception has been catched and the a message has been logged. 如您所见,已捕获到do_stuff_2异常,并且已记录一条消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM