Python 查找所有内置异常的简单函数在直接运行时起作用,但在用作导入模块时失败,无法进行回溯

Python 查找所有内置异常的简单函数在直接运行时起作用,但在用作导入模块时失败,无法进行回溯,python,python-3.x,exception,Python,Python 3.x,Exception,我有一个函数,它应该生成所有内置异常的元组(用于except(Exception1、Exception2等)作为错误:form),当我正常运行它时,它工作得很好 def get_exceptions(): exceptionList = [] for item in dir(__builtins__): if item.find('Error') != -1: exec('exceptionList.append({})'.format

我有一个函数,它应该生成所有内置异常的元组(用于
except(Exception1、Exception2等)作为错误:
form),当我正常运行它时,它工作得很好

def get_exceptions():

    exceptionList = []

    for item in dir(__builtins__):
        if item.find('Error') != -1:
            exec('exceptionList.append({})'.format(item))

    return tuple(exceptionList)

if __name__ == '__main__':
    print(get_exceptions())
运行时:

(<class 'ArithmeticError'>, <class 'AssertionError'>, <class 'AttributeError'>, <class 'BlockingIOError'>, <class 'BrokenPipeError'>, <class 'BufferError'>, <class 'ChildProcessError'>, <class 'ConnectionAbortedError'>, <class 'ConnectionError'>, <class 'ConnectionRefusedError'>, <class 'ConnectionResetError'>, <class 'EOFError'>, <class 'OSError'>, <class 'FileExistsError'>, <class 'FileNotFoundError'>, <class 'FloatingPointError'>, <class 'OSError'>, <class 'ImportError'>, <class 'IndentationError'>, <class 'IndexError'>, <class 'InterruptedError'>, <class 'IsADirectoryError'>, <class 'KeyError'>, <class 'LookupError'>, <class 'MemoryError'>, <class 'NameError'>, <class 'NotADirectoryError'>, <class 'NotImplementedError'>, <class 'OSError'>, <class 'OverflowError'>, <class 'PermissionError'>, <class 'ProcessLookupError'>, <class 'ReferenceError'>, <class 'RuntimeError'>, <class 'SyntaxError'>, <class 'SystemError'>, <class 'TabError'>, <class 'TimeoutError'>, <class 'TypeError'>, <class 'UnboundLocalError'>, <class 'UnicodeDecodeError'>, <class 'UnicodeEncodeError'>, <class 'UnicodeError'>, <class 'UnicodeTranslateError'>, <class 'ValueError'>, <class 'OSError'>, <class 'ZeroDivisionError'>)
什么也没发生

即使在文件中:

import list_exceptions
print(list_exceptions.get_exceptions())
我得到:

()
这似乎很奇怪。任何帮助都会很好! 顺便说一句,我看了这些,它们与我的想法没有太大关系。


如果您有任何问题,只需提问:)

这很有效,而且似乎是获取内置模块的常用技术

def get_exceptions():

    exceptionList = []

    for k in __builtins__.keys():
        if k.find('Error') != -1:
            exec('exceptionList.append({})'.format(k))

    return tuple(exceptionList)


if __name__ == '__main__':
    print(get_exceptions())

你的方法的根本问题是你依赖两件你不应该依赖的东西。第一个是
dir
,不应该依赖它的行为,因为它的存在主要是为了帮助交互式shell中的调试。从:

如果对象不提供
\uuuu dir\uuuu()
,则函数将尝试其 如果需要,最好从对象的
\uuu dict\uuu
属性收集信息 已定义,并从其类型对象。结果列表不可用 必须完整,并且当对象具有 自定义
\uuu getattr\uuuu()

注意因为提供
dir()
主要是为了方便在交互式提示下使用,所以它尝试提供一组有趣的 名称多于它试图提供严格或一致的 已定义的名称集,其详细行为可能会随着 释放。例如,元类属性不在结果列表中 当参数是一个类时

此外,您还可以使用
\uuuu内置变量
变量,该变量也是一个实现细节,来自:

作为一个实现细节,大多数模块的名称为
\uuuuu内置\uuuuu
作为其全球服务的一部分提供。
\uuuuuuuu内置项的值为
通常情况下,该模块或该模块的
\uuuu dict\uuuu
属性由于这是一个实现细节,因此可能不使用它 通过Python的替代实现

从本质上讲,你依赖于两件不可靠的事情。注意,在您的案例中实际发生的情况是,当您直接运行模块时,它返回实际的
内置模块
模块,但是,当导入模块时,
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。几张调试照片可能说明了这一点:

# builtinstest.py
def get_exceptions():

    print(type(__builtins__))
    print(dir(__builtins__))
从交互式口译员:

>>> import builtinstest
>>> builtinstest.get_exceptions()
<class 'dict'>
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
做你想做的事。注意,这会直接迭代这些值,因此您不会最终使用类似于
eval
exec
的内容,这在本例中是一种滥用。注意,这将捕获每个内置异常,例如警告(例如
BytesWarning
)和更深奥的内容,例如
SystemExit

最后 仅仅因为你能做到这一点,并不意味着你应该这样做。你声明的目的是:

我有一个函数,应该生成所有内置元素的元组 例外情况(用于
例外情况(例外情况1、例外情况2等)
as错误:
form)


好的,您可以只使用
except BaseException as error
,而不必一开始就繁琐地查找这些异常(事实上,
except
基本上是检查是否出现了任何错误的
。从根本上说,很少有任何好的理由有这样一个广泛的
except
子句。您应该始终尝试捕获尽可能狭窄的异常。

我使用的是
exec
函数,因此它是dds是实际的异常,而不是字符串。您可以使用
getattr(\uu内置项,item)
来实现类似的效果,好吧,那会是什么样子呢?我以前从未使用过
getattr
。在终端中,
item.find('Error')!=-1
始终为false。不知道为什么(现在),但这就是正在发生的事情。是的,很奇怪,我在windows上,每当我在IDE中或从任何命令行导入它时,它都不会工作。当我通过双击或从cmd或powershell运行它时,它工作得很好我得到:
Traceback(最近的一次调用):文件“C:\Users\Michael\Desktop\list\u exceptions.py”,第12行,打印文件“C:\Users\Michael\Desktop\list\u exceptions.py”中,第5行,用于k-in内置项:AttributeError:“模块”对象没有属性“键”>>>
我使用:
导入内置键=内置键。\uuuu dict\uuuuu
这很有效。哇。我对这个答案的细节感到惊讶。我刚刚学到了很多我不知道的东西,以及各种各样的酷东西。顺便说一句,我想能够捕捉所有异常并给出答案哼哼一个名字,因为我正在制作一个游戏,如果抛出一个异常,我想把异常放在一个消息框中,并将它报告给我。这就是为什么我不使用
除了:
,因为你不能做
,除了作为一件事。
谢谢你!@Michael是的,一般来说,你做
除了异常作为e
,有时你做不到只是为了报告一些事情,可能会进行清理,然后退出。再说一遍,你可能不应该让异常默默地通过,当然,这并不总是可能的,但对于游戏和内置异常,你应该处理它们或修复原因。我知道在任何地方放置一个
除了:
默认值是一个可怕的错误想法是因为回溯系统的整个想法是在意外事件发生时使程序崩溃。如果我的游戏中发生异常,它将打开一个消息框,尝试保存进度,并调用
sys.exit
>>> import builtinstest
>>> builtinstest.get_exceptions()
<class 'dict'>
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
import builtins
def get_exceptions_sanely():
    exception_list = []
    for obj in  vars(builtins).values():
        if isinstance(obj, type) and issubclass(obj, BaseException):
            exception_list.append(obj)
    return tuple(exception_list)