【问题标题】:Cleaning up an object only if an exception is raised仅在引发异常时清理对象
【发布时间】:2011-10-07 12:08:46
【问题描述】:

如果不是所有必须对其执行的操作都成功(也就是说,如果引发异常),我需要删除一个文件。它可以像使用 except: 一样简单,删除文件然后重新引发异常,但在这种情况下,如果无法在 中删除文件,原始异常将丢失除了 子句出于任何神秘的原因。

我能想到的最好的是:

try:
    file_path = "whatever.jpg"
    # do stuff with file
except:
    exception_raised = True
    raise
finally:
    try:
        if exception_raised:
            os.unlink(file_path)
    except:
        pass

return file_path   # everything OK

有人知道更好、更 Pythonic 的方法吗?

【问题讨论】:

    标签: python exception try-catch-finally


    【解决方案1】:

    如果您不想丢失,另一种选择是简单地存储异常:

    Python 3.x 版本:

    try:
        file_path = "whatever.jpg"
        # do stuff with file
    except BaseException as e:
        try:
            os.unlink(file_path)
        except Exception:
            traceback.print_exc()
        raise e
    

    Python 2.x 版本稍微复杂一些,因为您需要手动存储完整的异常信息(否则您会丢失回溯):

    try:
        file_path = "whatever.jpg"
        # do stuff with file
    except:
        e = sys.exc_info()
        try:
            os.unlink(file_path)
        except Exception:
            traceback.print_exc()
        raise e[0], e[1], e[2]
    

    编辑:仅在内部 try 块中捕获 Exception 的子类,因为您不想在此处捕获 SystemExitKeyboardInterrupt。还要报告在取消链接期间发生的任何异常,而不是仅仅删除它。

    【讨论】:

    • 当然,这不适用于不是从BaseException派生的异常。
    • @Mankarse:在 Python 3 中,所有异常都必须从 BaseException 派生。在 Python 2 中,异常类必须要么派生自 BaseExcpetion,要么是旧式类。旧式类现在已经淘汰了十年,所以如果你没有使用 非常 使用奇怪异常类的旧库,上面的代码应该是相当安全的。
    • @Mankarse:Python 2.x 的代码存在不同的问题——异常的回溯丢失了。修复此问题还删除了对BaseException 的(次要)限制。
    • 这正是我所忽略的,而正是我所寻找的:sys.exc_info()。完美的。谢谢,斯文。
    猜你喜欢
    • 1970-01-01
    • 2017-04-20
    • 2015-07-25
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多