简体   繁体   English

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

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

How would you catch exception within exception in python?您将如何在 python 的异常中捕获异常?

Consider the following case考虑以下情况

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)

Any thought of:任何想法:

  1. Rewriting to avoid double try ?重写以避免重复尝试

  2. Not necessarily this example, but in some case we cannot rewrite, how would you handle double try ?不一定是这个例子,但在某些情况下我们无法重写,你将如何处理双重尝试

A solution to avoid all this exception wrapping would be to useshutil.move避免所有这些异常包装的解决方案是使用shutil.move

shutil.move(filename, bak_filename)

If the destination already exists but is not a directory, it may be overwritten depending on os.rename() semantics.如果目标已存在但不是目录,则可能会根据 os.rename() 语义被覆盖。

If the destination is on the current filesystem, then os.rename() is used.如果目标位于当前文件系统上,则使用 os.rename()。 Otherwise, src is copied to dst using copy_function and then removed.否则,使用 copy_function 将 src 复制到 dst 然后删除。 In case of symlinks, a new symlink pointing to the target of src will be created in or as dst and src will be removed.在符号链接的情况下,将在 dst 中或作为 dst 创建一个指向 src 目标的新符号链接,并且将删除 src。

So it basically does what you're trying to do, but in a library which is available on all python distros.所以它基本上做了你想做的事情,但是在所有 python 发行版上都可用的库中。

Note that the performance may be bad if the file is big and the target file exists and os.rename refuses to overwrite it (completely depends on the operating system but for instance Windows will refuse to rename over an existing file), because the fallback when os.rename throws OSError is copying the source then deleting.请注意,如果文件很大并且目标文件存在并且os.rename拒绝覆盖它(完全取决于操作系统,例如 Windows 将拒绝重命名现有文件),则性能可能会很差,因为回退时os.rename抛出OSError正在复制源然后删除。 The implementation doesn't try to remove the file then rename again, because if rename fails, Python assumes that we're trying to rename across filesystems, and a copy+delete is in order in that case (this is exactly how Unix mv works).实现不会尝试删除文件然后再次重命名,因为如果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)

To workaround that possible file existence, a prior os.remove call wrapped in a try/except OSError statement could be done.要解决可能存在的文件,可以执行包含在try/except OSError语句中的先前os.remove调用。

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

Of course if bak_filename is locked/not deletable, an exception can still be raised by shutil.mode .当然,如果bak_filename被锁定/不可删除, shutil.mode仍然可以引发异常。 Also note that if we tried to delete the target file, os.rename will be as good as shutil.move .另请注意,如果我们尝试删除目标文件, os.rename将与shutil.move一样好。 If the target file could not be deleted, the operation can't succeed anyway.如果无法删除目标文件,则无论如何操作都不会成功。

You can read more on Exception Chaining .您可以阅读更多关于异常链接的信息。 But, that's for Python 3但是,这是针对 Python 3

In Python 2, you can store your exception in a variable, then raise it again explicitly like this:在 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