无论如何,最终是否确保某些代码自动获得 运行?

Does finally ensure some code gets run atomically, no matter what?

假设我要编写一个 Python 脚本来捕获 KeyboardInterrupt 异常,以便能够被用户使用 Ctrl+ 终止C平安

但是,我无法将所有关键操作(如文件写入)放入 catch 块中,因为它依赖于局部变量并确保后续的 Ctrl+C反正不破

使用带有空 (pass) try 部分和 finally 部分内的所有代码的 try-catch 块来定义此代码段是否有效并且是一种好的做法"atomic, interrupt-safe code" 哪个不会中途被打断?

示例:

try:
    with open("file.txt", "w") as f:
        for i in range(1000000):
            # imagine something useful that takes very long instead
            data = str(data ** (data ** data))
            try:
                pass
            finally:
                # ensure that this code is not interrupted to prevent file corruption:
                f.write(data)

except KeyboardInterrupt:
        print("User aborted, data created so far saved in file.txt")
        exit(0)

在此示例中,我不关心当前生成的数据字符串,即可以中断创建并且不会触发写入。但是一旦写入开始,它 必须 完成,这就是我想要确保的。另外,如果在 finally 子句中执行写入时发生异常(或键盘中断)会发生什么情况?

finally 中的代码也可以仍然被中断。 Python 对此不作任何保证;它所保证的是,在 try 套件完成后或 try 套件中出现异常时,执行将切换到 finally 套件。 try 只能处理在其范围内引发的异常,不能处理范围外,而 finally 在该范围外。

因此,在 pass 语句中使用 try 没有意义 。 pass 是空操作,它永远不会被打断,但是 finally 套件仍然很容易被打断。

您需要选择不同的技术。您可以写入一个单独的文件,并在成功完成后将其移动到位;例如,OS 保证文件移动是原子的。或者记录您上次成功写入的位置,如果下一次写入被中断,则将文件截断到该点。或者在您的文件中写入标记,表示记录成功,以便读取知道要忽略什么。

在你的情况下,没有问题,因为文件写入是原子的,但如果你有一些文件对象实现,那更复杂,你的 try-except 在错误的地方。您必须围绕写入放置异常处理:

try:
    f.write(data)
except:
    #do some action to restore file integrity
    raise

例如,如果你写二进制数据,你可以这样:

filepos = f.tell()
try:
    f.write(data)
except:
    # remove the already written data
    f.seek(filepos)
    f.truncate()
    raise