让我们看看这个例子:
with mycontextmanager(arg1='value', arg2=False):
print 'Executed'
是否有办法在基于参数的上下文管理器中不执行代码块(print 'Executed'
),例如:当arg2不是False时?
答案 0 :(得分:1)
另一个选项是使用特殊的ConditionalExecution
上下文管理器,其__enter__
方法返回一个有条件地引发SkipExecution
异常的操作。 __exit__
方法仅抑制此异常。
如下所示:
class SkipExecution(Exception): pass
class ConditionalExecution(object):
def __init__(self, value, arg):
self.value = value
self.arg = arg
def __enter__(self):
def action():
if not self.arg:
raise SkipExecution()
return action
def __exit__(self, exc_type, exc_value, tb):
if exc_type is SkipExecution:
return True
return False
用作:
In [17]: with ConditionalExecution(1, True) as check_execution:
...: check_execution()
...: print('Hello')
...:
Hello
In [18]: with ConditionalExecution(1, False) as check_execution:
...: check_execution()
...: print('Hello')
In [19]:
但问题是您必须添加对返回值的调用。
问题是__exit__
被称为当且仅当 __enter__
成功返回时,这意味着您无法在__enter__
中引发异常以阻止代码块的执行。
如果您愿意,可以修改此解决方案,以便可以在第一行完成对check_execution()
的调用,例如:
In [29]: with ConditionalExecution(1, True) as check_execution, check_execution():
...: print('Hello')
Hello
In [30]: with ConditionalExecution(1, False) as check_execution, check_execution():
...: print('Hello')
使用Skipper
助手上下文管理器:
class SkipExecution(Exception): pass
class Skipper(object):
def __init__(self, func):
self.func = func
def __call__(self):
return self.func() or self
def __enter__(self):
return self
def __exit__(self, *args):
pass
class ConditionalExecution(object):
def __init__(self, value, arg):
self.value = value
self.arg = arg
def __enter__(self):
def action():
if not self.arg:
raise SkipExecution()
return Skipper(action)
def __exit__(self, exc_type, exc_value, tb):
if exc_type is SkipExecution:
return True
return False
如果没有至少一个显式的函数调用,我认为无论如何都没有这样做。如上例所示。
答案 1 :(得分:0)
也许这样,假设你的上下文管理器支持一个“what”属性,它暴露了初始化时在arg2中得到的值:
with mycontextmanager(arg1='value', arg2=False) as ctx:
if ctx.whatever:
print 'Executed'