繁体   English   中英

您将如何在 except 子句中捕获 python 异常

[英]How would you catch python Exception inside an except clause

您将如何在 python 的异常中捕获异常?

考虑以下情况

bak_filename = filename + ".bak"
#This try is needed because if bak_filename existed, rename will fail
try:
   os.rename(filename, bak_filename)
except WindowsError:
   #However, os.remove may still fail e.g. file in use. How would you handle this exception within except clause ?
   #try and except around this os.remove?  
   os.remove(bak_filename)

   os.rename(filename, bak_filename)

任何想法:

  1. 重写以避免重复尝试

  2. 不一定是这个例子,但在某些情况下我们无法重写,你将如何处理双重尝试

避免所有这些异常包装的解决方案是使用shutil.move

shutil.move(filename, bak_filename)

如果目标已存在但不是目录,则可能会根据 os.rename() 语义被覆盖。

如果目标位于当前文件系统上,则使用 os.rename()。 否则,使用 copy_function 将 src 复制到 dst 然后删除。 在符号链接的情况下,将在 dst 中或作为 dst 创建一个指向 src 目标的新符号链接,并且将删除 src。

所以它基本上做了你想做的事情,但是在所有 python 发行版上都可用的库中。

请注意,如果文件很大并且目标文件存在并且os.rename拒绝覆盖它(完全取决于操作系统,例如 Windows 将拒绝重命名现有文件),则性能可能会很差,因为回退时os.rename抛出OSError正在复制源然后删除。 实现不会尝试删除文件然后再次重命名,因为如果rename失败,Python 会假设我们正在尝试跨文件系统重命名,并且在这种情况下需要复制+删除(这正是 Unix mv的工作方式)。

try:
    os.rename(src, real_dst)
except OSError:
    if os.path.islink(src):
        ...
    else:
        copy_function(src, real_dst)
        os.unlink(src)

要解决可能存在的文件,可以执行包含在try/except OSError语句中的先前os.remove调用。

try:
   os.remove(bak_filename)
except OSError:
   pass
shutil.move(filename, bak_filename)  # or os.rename(filename, bak_filename)

当然,如果bak_filename被锁定/不可删除, shutil.mode仍然可以引发异常。 另请注意,如果我们尝试删除目标文件, os.rename将与shutil.move一样好。 如果无法删除目标文件,则无论如何操作都不会成功。

您可以阅读更多关于异常链接的信息。 但是,这是针对 Python 3

在 Python 2 中,您可以将异常存储在变量中,然后像这样显式地再次引发它:

try:
    do something
except Exception as e:
    try:
        do something again
    except:
        pass
    raise e

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM