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