Python 有没有办法阻止上下文管理器输入'with'正文?

Python 有没有办法阻止上下文管理器输入'with'正文?,python,Python,我试过这个: @contextmanager def changed_dir(dirname, msg="nothing to do.."): if changed(dirname): yield else: print msg return 但是,当我尝试使用它时: with changed_dir("foo/bar"): print "something in foo/bar was changed" 我受到了如下的欢迎:

我试过这个:

@contextmanager
def changed_dir(dirname, msg="nothing to do.."):
    if changed(dirname):
        yield
    else:
        print msg
    return
但是,当我尝试使用它时:

with changed_dir("foo/bar"):
    print "something in foo/bar was changed"
我受到了如下的欢迎:

RuntimeError: generator didn't yield
有什么办法可以让它工作吗

更新:许多人似乎被示例的简单性所困扰。这里有一个更复杂的例子来说明同一点

@contextmanager
def changed_dir(dirname, msg="..."):
    cn = db.get_connection(...)
    try:
        cn.execute("insert ...")
        if changed(dirname):
            cn.execute(...)
            yield
            os.mkdirs(os.path.join('backup', dirname))
            # copy the modified tree.. 
            # etc.
        else:
            cn.execute(...)
            print msg
        cn.commit()
    except:
        cn.rollback()
        # cleanup from mkdirs call...
    finally:
        cn.close()
上面的衬里仍然是唯一的解决方案吗?

,但您可能不应该这样做。使用
if/else
。事实上,只需使用上下文管理器中的
if/else

msg = "nothing to do.."

if changed(dirname):
    print "something in foo/bar was changed"
else:
    print msg
更新:

作为对您更新的回应,我将这样做:

@contextmanager
def db_context_manager():  # Name this better
    cn = db.get_connection(...)
    try:
        cn.execute("insert ...")
        yield
        cn.commit()
    except:
        cn.rollback()
    finally:
        cn.close()

with db_context_manager():
    if changed(dirname):
        do_stuff()

Guido在PEP-0343中的评论似乎表明该用例是COP乙酸的,并且基于我提出的PEP中的示例(我查看了@Cyphase答案中的链接,但这似乎不必要地复杂):


这似乎和大多数ContextManager一样简单(但不像我使用decorator时那么简单)

您的问题标题似乎与问题正文不一致。我可能明白你的意思,但你应该澄清一下。为什么不使用if语句呢?这听起来非常像
if/else
@thebjorn,你真的应该使用
if/else
<代码>如果条件:do_stuff();;另外:簿记()@thebjorn,我认为你应该展示你实际上在做什么;这样,要么我们可以吃我们的帽子,要么我们可以说服你,你不需要这样做。这不会悄悄地跳过带有块的
。不,不幸的是没有。它不执行with块,但NoChange异常会转义,并且永远不会调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuu
:-(有没有简单的方法来修复它?
class changed_dir(object):
    class NoChange(ValueError):
        pass

    def __init__(self, dirname, msg="nothing to do"):
        self.dirname = dirname
        self.msg = msg

    def __enter__(self):
        if changed(self.dirname):
            return
        else:
            print self.msg
            raise changed_dir.NoChange()

    def __exit__(self, type, value, traceback):
        return isinstance(value, changed_dir.NoChange)