【问题标题】:Python - Exception seems to be skipping out of with block [duplicate]Python - 异常似乎正在跳过块[重复]
【发布时间】:2014-06-08 19:05:45
【问题描述】:

以下是相关代码:

    @contextlib.contextmanager
    def make_temp_dir():
      temp_dir = tempfile.mkdtemp()
      yield temp_dir
      shutil.rmtree(temp_dir)

    with make_temp_dir(listing_id) as tmpdir:
      pass
      # Sometimes something in here throws an exception that gets caught higher up

好的,写完这一切,我现在明白发生了什么。我正在使用装饰器创建的上下文管理器中的 exit 方法 正在运行,但这当然不会将流返回到我的生成器。

那么应该我该怎么做呢?

【问题讨论】:

  • 如果想在上下文管理器中捕获异常,需要照常写一个try/except。见this question

标签: python with-statement contextmanager


【解决方案1】:

这里发生的情况如下:

  • __enter__() 上,生成器启动。它产生的返回值是__enter__()
  • __exit__() 上,以正常方式或通过注入异常来恢复生成器。相关代码在$PYTHONROOT/contextlib.py 中,您可以看到在生成器上调用了next()throw()

如果在生成器上调用throw(),则会在它内部引发异常,这正是我们上次离开它的位置,即。 e.然后yield 表达式引发异常。

因此,您必须将yield 包含在try: 语句中。只有这样,您才能对异常做一些事情。

如果您不这样做,您的生成器将在不执行任何操作的情况下引发异常。

你可能想要

@contextlib.contextmanager
def make_temp_dir():
    temp_dir = tempfile.mkdtemp()
    try:
        yield temp_dir
    finally:
        shutil.rmtree(temp_dir)

【讨论】:

  • 谢谢。所以这个例外正在我的发电机内部重新提出,对吧?我想我的意思是,这个异常仍将由我的with 之外的现有except 处理?所以它的工作方式就像.. 引发异常.. __exit__() 被调用,将异常传递给 throw(),然后异常由我的外部 except 处理?谢谢
  • @ShaneH 是的,但它并不是真正的“外部”。 with 语句有点映射到生成器内的 try...finally
猜你喜欢
  • 1970-01-01
  • 2020-08-27
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多