【问题标题】:How would you catch python Exception inside an except clause您将如何在 except 子句中捕获 python 异常
【发布时间】:2020-02-17 22:14:22
【问题描述】:

如何在 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. 不一定是这个例子,但在某些情况下我们无法重写,你将如何处理双重try?

【问题讨论】:

  • 将try/except 放在os.remove() 周围有什么问题?
  • 只是我的一些经验和阅读后我的脑后,它会变得混乱且难以调试。

标签: python file exception try-catch


【解决方案1】:

避免所有这些异常包装的解决方案是使用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 时的回退是复制源然后删除。实现不会尝试删除文件 then 再次重命名,因为如果 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 一样好。如果无法删除目标文件,则无论如何操作都不会成功。

【讨论】:

  • 听起来是个有趣的包,但我没有管理员权限随意安装包,需要坚持使用 os
  • 你不需要安装这个。这是内置。
【解决方案2】:

您可以在Exception Chaining 上阅读更多信息。但是,这适用于 Python 3

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

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

【讨论】:

    猜你喜欢
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多