【问题标题】:Catch exception throw from inside of the with statement从 with 语句内部捕获异常抛出
【发布时间】:2011-12-07 02:58:45
【问题描述】:
zip_file_name = "not_exist.py"

try:
   with zipfile.ZipFile(zip_file_name) as f_handle:
       print("open it successfully")
except (zipfile.BadZipfile, zipfile.LargeZipFile), e:
       print(e)

这是处理 with 语句引发的异常的正确方法吗?

【问题讨论】:

标签: python


【解决方案1】:

是的,没关系。

另一种选择是:

try:
   f_handle = zipfile.ZipFile(zip_file_name)
   # no more code here
except (zipfile.BadZipfile, zipfile.LargeZipFile), e:
   print(e)
else:
   with f_handle:
      print("open it successfully")

这可以防止您在 except 处理程序中意外地从 with 语句的主体中捕获异常。

【讨论】:

  • 如果在获取资源后发生异常,这不会给 ZipFile 清理的机会(ContextManager 的 __exit__ 部分)。如果你打算走这条路,我建议改用 try/except/finally。
  • @Chris Phillips:嗯....在赋值成功和调用 with 语句之间会发生什么异常?
  • @Mark,我猜 Chris 已经假设可以在赋值语句之后添加更多代码。我在你的代码中做了评论,发现它对他有用。
【解决方案2】:

是的,这就是您希望在with 语句中处理异常的方式。 ContextManagers(实现with 语句背后的行为)可以处理异常,但只能正确清理对象使用的资源。

这是来自relevant documentation的sn-p:

如果 BLOCK 引发异常,上下文管理器的 exit() 方法 使用三个参数调用,异常详细信息(类型、值、 traceback,与 sys.exc_info() 返回的值相同,也可以 如果没有发生异常,则为 None)。方法的返回值控件 是否重新引发异常:任何错误值都会重新引发 异常,True 将导致抑制它。你只会很少 想压制异常,因为如果你做的作者 包含‘with’语句的代码永远不会意识到发生了什么 错了。

【讨论】:

  • 虽然这是正确的,但这并不是全部。该文档指的是来自 with 语句的 BLOCK 部分的异常。它适用于返回 ContextManager 的表达式的异常。如果您查看 OP 捕获的异常类型,似乎 OP 对后者感兴趣。
猜你喜欢
  • 2018-08-31
  • 2012-07-27
  • 1970-01-01
  • 2010-10-17
  • 2011-07-09
  • 1970-01-01
  • 2011-06-27
  • 2013-06-24
  • 2011-05-07
相关资源
最近更新 更多