Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何安全地确定捕获的异常的原因?_Python_Python 3.x_Exception Handling - Fatal编程技术网

Python 如何安全地确定捕获的异常的原因?

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异常的原因是否是因为我

在Python中,各种标准库函数(当然还有其他代码)都可以抛出许多错误。由于许多原因可能会引发特定的异常,您可能希望了解它是否是由于特定原因引发的

例如,在Windows中,如果在文件被另一个进程锁定时尝试移动该文件,则可能会出现
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)@JLPeyret
vars(e)
为我返回一个空字典(
e.。\uuuuu dict\uuuu
也是一个空字典,)。有趣;我认为对象中的
\uuuu dict\uuuu
属性列出了对象中的所有其他属性,但显然属性可以是不可写的,也可以是不可修改的。此外,
e
中的属性似乎实现为,这是我以前从未听说过的。这可能有用。谢谢。因此模块中列出了posix
errno
值。是否有一些模块也列出了
winerror
值?对于pywin32,有,但我没有,可能是因为我运行的是64位Python。谢谢。b中的
a构造肯定比我使用的构造更方便。谢谢,我使用了
winerror
属性。你知道是否有一些模块列出了
winerror
值(这不仅适用于32位Python),例如,我可以在其中找到
ERROR\u SHARING\u违规
,而不必将相应的值硬编码到我的代码中(例如
ERROR\u SHARING\u违规
),我不知道任何官方模块。但是,web上有许多文件列出了它们,例如,您可以在自定义模块中剪切并粘贴相关部分。