如何确定特定异常类定义的模块

3 投票
5 回答
509 浏览
提问于 2025-04-15 16:51

注意:我修改了我的问题标题,让它更准确地反映我真正想知道的内容。在最初的标题和问题内容中,我提到了抛出异常的来源;我想说的是,应该提到异常类定义所在的模块。这一点可以通过下面的回答看到,原问题的答案是异常是从cursor.execute和cursor.next的调用中抛出的——这当然不是你写try/except块所需的信息。

举个例子(这个问题和SQLite或PySQLite模块没有直接关系):

from pysqlite2 import dbapi2 as SQ

try:
    cursor.execute('CREATE TABLE pname (id INTEGER PRIMARY KEY, name VARCHARS(50)')
except SQ.OperationalError:
    print("{0}, {1}".format("table already exists", "... 'CREATE' ignored")) 
#
cursor.execute('SELECT * FROM pname')
while 1:
    try:
        print(cursor.next())
    except StopIteration:
        break
#

我让这两个代码片段出错,以查看抛出的异常,然后编写了try/finally块——但这并没有告诉我异常类是在哪个模块中定义的。在我的例子中,只有一个导入的模块,但如果有更多模块,我想知道一个有经验的Python程序员是如何识别异常来源的(目前我的方法是搜索文档,直到我碰巧找到为止)。

[是的,我知道在SO上有一个几乎相同的问题——但那是关于C#的,而不是Python,而且如果你读了作者修改后的版本,你会发现他有不同的问题要解决。]

5 个回答

2

你可以使用Python的inspect模块和通用的异常处理,方法如下:

from inspect import getmodule
try:
    # attempt some task
except Exception, e:
    print getmodule(e)

这样做会输出模块及其路径,结果如下:

<module 'some.module' from '/path/to/some/module.pyc'>
4

通常情况下,我会直接查看文档。Python模块或函数的文档中会有一部分是列出它定义的异常。如果没有列出任何异常,我就会假设我需要找的是Python内置的异常。

顺便提一下,StopIteration异常是Python中任何“可迭代”对象用来告诉你数据已经到头的标准方式。这个循环:

cursor.execute('SELECT * FROM pname')
while 1:
    try:
        print(cursor.next())
    except StopIteration:
        break

可以写成:

cursor.execute('SELECT * FROM pname')
for x in cursor:
    print(x)

编辑:我得说,尽管我很自信地认为异常会有文档说明,但我在Python的文档帮助或dbapi2的网页帮助中找不到这样的列表。在这种情况下,我想我就像你一样:在谷歌上搜索这个异常的名字,看看能找到什么!

5

第二个[[异常被抛出]]是来自Python的核心模块

这不对:它是从cursor.next的调用中抛出的,正好和第一个异常是从cursor.execute的调用中抛出的一样——很难理解你为什么会这么断言,但这与事实相悖,依然是事实。

如果你是在说某个异常类是在哪个模块中定义的,而不是你所说的它是从哪里抛出的,那当然是完全不同的事情:

try:
  ...whatever...
except Exception, e:
  print "caught an exception defined in module", e.__class__.__module__

内置异常实际上是在exceptions模块中定义的,这段代码也会告诉你。当然,一旦你有了模块名(这段代码给了你),你可以进一步探索,比如获取模块对象(只需通过模块名索引sys.modules)等等。

撰写回答