Python 如何安全地确定捕获的异常的原因?
在Python中,各种标准库函数(当然还有其他代码)都可以抛出许多错误。由于许多原因可能会引发特定的异常,您可能希望了解它是否是由于特定原因引发的 例如,在Windows中,如果在文件被另一个进程锁定时尝试移动该文件,则可能会出现Python 如何安全地确定捕获的异常的原因?,python,python-3.x,exception-handling,Python,Python 3.x,Exception Handling,在Python中,各种标准库函数(当然还有其他代码)都可以抛出许多错误。由于许多原因可能会引发特定的异常,您可能希望了解它是否是由于特定原因引发的 例如,在Windows中,如果在文件被另一个进程锁定时尝试移动该文件,则可能会出现PermissionError: PermissionError:[WinError 32]进程无法访问该文件,因为另一个进程正在使用它:“C:\\Path\\to\\The\\file” 在我的例子中,我想确定引发PermissionError异常的原因是否是因为我
PermissionError
:
PermissionError:[WinError 32]进程无法访问该文件,因为另一个进程正在使用它:“C:\\Path\\to\\The\\file”
在我的例子中,我想确定引发PermissionError
异常的原因是否是因为我尝试移动的文件被锁定,而我目前通过查看捕获的异常中的错误消息来执行此操作:
try:
# Move file
os.rename(source_path, dest_path)
except PermissionError as e:
if str(e).find('The process cannot access the file because it is being used by another process') != -1:
# File not unlocked yet; do something, e.g. wait a moment and try again
else:
# Exception thrown for some other reason; do something else
但是,要检查str(e)
是否包含特定的错误消息,因为子字符串感觉不完全安全,因为我还没有看到在源文件锁定时将哪些消息分配给os.rename
引发的异常,或者应该抛出什么类型的异常,或者甚至应该抛出异常。因此,这种行为可能会在Python的未来版本中发生变化,或者在不同的Python实现中有所不同
因此,如果我们可以假设将引发
PermissionError
异常,那么如何安全地确定是否因为我试图访问锁定的文件而引发了PermissionError
异常?或者,如果我们不能假设,我如何才能安全地实现我的应用程序当前实现的相同功能?在Windows上,使用异常字符串是安全的
它将始终是“该进程无法访问该文件,因为它正被另一个进程使用”
你总能做到
if "The process cannot access the file because it is being used by another process" in str(e):
#file is locked
pass
标准python异常使用C
errno
代码,您可以使用e.errno
进行访问
在mac/linux上,您可以看到
在windows上,您可以使用
e.winerror
访问windows操作系统提供的其他错误代码。然后,您可以使用查找正确的代码进行检查。Lærne是正确的,要正确确定错误原因,只需根据其errno
属性进行检查
可用错误符号列表位于模块中,您可以通过对照模块中定义的符号进行检查来导入和使用该模块。一个简单的例子:
import os, errno
try:
os.remove(filename)
except OSError as e:
if e.errno != errno.ENOENT:
raise
这再次引发了异常。你所说的“安全”是什么意思?@martineau所说的“安全”在这种情况下,我的意思是,如果我换到另一个版本的Python或另一个Python解释器,就不会中断。我并不是说我目前的做法会失败,我只是不确定它不会。在这种情况下,“最安全”的做法是将
异常捕获为e:
,并在屏幕上打印一条错误消息,说明无法访问该文件,以及str(e)
。未来并没有保障。下一步最安全(也是最实际)的做法是将其变得相当具体,并假设未来将是兼容的,至少在可预见的未来是如此。后者通常是这样的,因为语言创建者/维护者不喜欢破坏大量现有代码。除了str(e)
,您还可以看看e的实际内涵<例如,code>vars(e)可能会显示除人类可读消息之外的其他内容。可能有点用。例如,我得到的一个sqlalchemy异常有一个嵌入的原始异常,我可以通过解析str(e)@JLPeyretvars(e)
为我返回一个空字典(e.。\uuuuu dict\uuuu
也是一个空字典,)。有趣;我认为对象中的\uuuu dict\uuuu
属性列出了对象中的所有其他属性,但显然属性可以是不可写的,也可以是不可修改的。此外,e
中的属性似乎实现为,这是我以前从未听说过的。这可能有用。谢谢。因此模块中列出了posixerrno
值。是否有一些模块也列出了winerror
值?对于pywin32,有,但我没有,可能是因为我运行的是64位Python。谢谢。b中的a构造肯定比我使用的构造更方便。谢谢,我使用了winerror
属性。你知道是否有一些模块列出了winerror
值(这不仅适用于32位Python),例如,我可以在其中找到ERROR\u SHARING\u违规
,而不必将相应的值硬编码到我的代码中(例如ERROR\u SHARING\u违规
),我不知道任何官方模块。但是,web上有许多文件列出了它们,例如,您可以在自定义模块中剪切并粘贴相关部分。