【问题标题】:Compressing two Python try/except blocks into one without changing behavior将两个 Python try/except 块压缩为一个而不改变行为
【发布时间】:2013-03-18 19:41:34
【问题描述】:

我正在为标准库的shutil.rmtree() 中的错误处理中的一个现有错误开发补丁,我遇到了以下代码:

try:
    orig_st = os.lstat(path)
except Exception:
    onerror(os.lstat, path, sys.exc_info())
    return
try:
    fd = os.open(path, os.O_RDONLY)
except Exception:
    onerror(os.lstat, path, sys.exc_info())
    return

在应用我的更改以简化实施之前,我想将其简化为以下内容:

try:
    orig_st = os.lstat(path)
    fd = os.open(path, os.O_RDONLY)
except Exception:
    onerror(os.lstat, path, sys.exc_info())
    return

两个代码示例之间的行为是否会有所不同?

【问题讨论】:

  • 不要抓到Exception。而是捕获特定的异常。
  • @MartijnPieters 我知道这是最佳实践,但不幸的是我无法打破shutils.rmtree API 中的向后兼容性,因此我必须保持onerror 的当前处理,直到该功能被弃用和删除。 (onerror 系统的混乱和复杂性实际上是我们试图用这个补丁修复的,但这将是一个多步骤的过程。)

标签: python exception exception-handling python-3.x


【解决方案1】:

在单线程应用程序中,两者没有区别。不过,在多线程应用程序中,“路径”可能会在两个尝试例外之间发生变化。

此代码是在修复符号链接攻击漏洞 (http://bugs.python.org/issue4489) 的补丁中引入的。也许您应该在更改后要求原始提交者进行代码审查。根据http://hg.python.org/cpython/annotate/c910af2e3c98/Lib/shutil.py#434,是Hynek Schlawack。

【讨论】:

  • 谢谢。我现在在 PyCon sprint 中,错误作者实际上在这里,或者我可以咨询其他核心开发人员以了解最佳行动方案。
【解决方案2】:

我认为这两种情况是相同的,但只是因为每个异常块内都有一个return,这意味着如果第一个遇到异常,第二个try...except 块实际上不会被执行。

如果第一个try...except没有return,那么即使在第一个块中遇到异常,第二个try...except块也会被执行,这两种情况不会完全相同。

【讨论】:

    【解决方案3】:

    我认为他们将其拆分的原因是,如果它在第一次尝试时捕获了异常,那么它仍然会为 fd 设置一个值。按照您编写的方式,如果异常在代码的第一位(即 orig_st)被捕获,那么它将永远不会设置 fd,因为它已经通过了它,即使它可能不包含异常。

    【讨论】:

    • 但是异常块中的return 无论如何都会阻止第二个块的发生。我认为这两种情况是等价的,只要每个块 returns 出现异常。
    • 哎呀,没有看到回报。
    猜你喜欢
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 2020-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    相关资源
    最近更新 更多