我有一些需要用函数包装的代码块。
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”和“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:生成器没有产生
答案 0 :(得分:0)
你可以传递一个函数。
pass_this_in = lambda : print("I just did some stuff")
如果要减少“pass_this_in”定义位,则可以使用lambda function definitions:
$ gcc -g -W -Wall -Wextra x.c -o x
x.c: In function 'append':
x.c:56:5: warning: format '%d' expects argument of type 'int *', but argument 6 has type 'int' [-Wformat=]
int r = sscanf(input, "%s%s%s%d", command, fName, lName, score);
^
x.c:56:9: warning: 'score' is used uninitialized in this function [-Wuninitialized]
int r = sscanf(input, "%s%s%s%d", command, fName, lName, score);
^
$ valgrind ./x test.txt
==16814== Memcheck, a memory error detector
==16814== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==16814== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==16814== Command: ./x test.txt
==16814==
a b c 123
==16814== Use of uninitialised value of size 8
==16814== at 0x4E9B2D9: _IO_vfscanf (in /lib64/libc-2.20.so)
==16814== by 0x4EA9BAB: __isoc99_vsscanf (in /lib64/libc-2.20.so)
==16814== by 0x4EA9B26: __isoc99_sscanf (in /lib64/libc-2.20.so)
==16814== by 0x400A4A: append (x.c:56)
==16814== by 0x400993: runCommand (x.c:39)
==16814== by 0x4008F9: main (x.c:26)
答案 1 :(得分:0)
我不确定上下文管理器是实现您想要的好方法。上下文管理器的目标是提供一种机制来打开/实例化资源,提供(或不访问)资源,并在您不再需要时自动关闭/清理它。
恕我直言,你需要的是decorator。 装饰器旨在围绕函数调用执行代码。它会强迫你将每个代码块放在一个函数中,但我不认为它是如此困难。您可以像这样实现它:
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
函数,它实际上会在装饰函数调用周围运行代码。在此函数中,仅在try/except
被评估为True时才在config.DEVELOPMENT
结构内调用修饰函数。如果发生异常,logger
用于记录信息。do_stuff_1
,do_stuff_2
并用check_dev_config
装饰器生成器修饰,为其赋予config
和{{ 1}}。logger
异常,并且已记录消息。