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)