我正在尝试编写支持以下语义的代码:
with scope('action_name') as s:
do_something()
...
do_some_other_stuff()
范围等(设置,清理)应决定是否应运行此部分
例如,如果用户将程序配置为绕过'action_name',则在评估Scope()之后,将执行do_some_other_stuff()而不先调用do_something()。
我尝试使用此上下文管理器来执行此操作:
@contextmanager
def scope(action):
if action != 'bypass':
yield
但获得RuntimeError: generator didn't yield
例外(当action
为'bypass'
时)
我正在寻找一种方法来支持这一点,而不会回到更详细的可选实现:
with scope('action_name') as s:
if s.should_run():
do_something()
...
do_some_other_stuff()
有谁知道我怎么做到这一点?
谢谢!
P.S。我正在使用python2.7
编辑:
解决方案不一定要依赖with
语句。没有它,我只是不知道如何表达它。本质上,我想要一个上下文形式的东西(支持设置和自动清理,与包含的逻辑无关),并允许基于传递给设置方法并在配置中选择的参数进行条件执行。
我还考虑过使用装饰器的可能解决方案。示例:
@scope('action_name') # if 'action_name' in allowed actions, do:
# setup()
# do_action_name()
# cleanup()
# otherwise return
def do_action_name()
do_something()
但我不想基于这些范围强制执行过多的内部结构(即代码如何划分为函数)。
有人有一些创意吗?
答案 0 :(得分:7)
您正在尝试修改基本语言构造的预期行为。这绝不是一个好主意,只会导致混乱。
你的解决方法没有任何问题,但你可以稍微简化一下。
@contextmanager
def scope(action):
yield action != 'bypass'
with scope('action_name') as s:
if s:
do_something()
...
do_some_other_stuff()
您的scope
可能是__enter__
方法返回有用对象或None
的类,它将以相同的方式使用。
答案 1 :(得分:2)
以下似乎有效:
from contextlib import contextmanager
@contextmanager
def skippable():
try:
yield
except RuntimeError as e:
if e.message != "generator didn't yield":
raise
@contextmanager
def context_if_condition():
if False:
yield True
with skippable(), context_if_condition() as ctx:
print "won't run"
考虑:
context_if_condition
,则无法使用skippable
,但无法强制执行/删除冗余答案 2 :(得分:1)
我不认为这可以做到。我尝试将上下文管理器作为一个类实现,并且没有办法强制块来引发一个异常,随后会被__exit__()
方法压制。
答案 3 :(得分:-1)
我有与您相同的用例,并且遇到了自您发布问题以来有人帮助开发的conditional library。
从网站上看,它的用途如下:
with conditional(CONDITION, CONTEXTMANAGER()):
BODY()