【问题标题】:Catching exceptions that don't inherit from Exception捕获不从 Exception 继承的异常
【发布时间】:2015-02-01 14:20:15
【问题描述】:

我有一个使用查询或命令调用的数据库访问模块。它弄清楚如何处理数据库,并尝试这样做。但是,例如,如果查询或命令字符串是病态的,则对底层 PGDB 模块的调用可能会引发异常。

PGDB(来自 PostgreSQL 下)返回了一些非常有用的信息,特别指出在查询或命令中发现了哪些错误。 PGD​​B 的各种函数的这种用法检索该信息:

try:
    pgdb.dothing(mod.withx)
except Exception, e:
    mod.error = 'pgdb.dothing('+str(type(mod.withx))+str(mod.withx)+') failed with: '+str(e)

然后当类返回失败时,对象包含 .error 和 viola 中的消息,我可以在查询或命令中修复我的愚蠢。

这一切似乎都运行良好——(在 Python 2.2.2 中,有朝一日可能会更改为 2.higher ......但现在不会——永远不会,永远不会更改为 3.whatever)

但是...我发现了一点不透明性:“异常不必从异常继承。因此简单的'except:'捕获所有异常,不仅是系统异常。字符串异常是一个例子不继承自 Exception 的异常"

所以问题来了:我为什么要关心?如果抛出异常,我想知道为什么。我不在乎它来自哪里,真的,我只想要错误消息,而且我当然不希望 Python 崩溃。这将包括错误是否来自字符串事物或其他。所以除了抓住一切都很好。或者应该是。

是不是异常的参数意味着,如果它来自例如字符串内部,我不会捕获错误?然后,代码将因未捕获的异常而停止?然后我需要为每种“不从异常继承”的类型进行一系列捕获,以获得我想要的行为?像这样的:

try:
    pgdb.dothing(mod.withx)
except Exception, e:
    mod.error = 'pgdb.dothing('+str(type(mod.withx))+str(mod.withx)+') failed with: '+str(e)
except:
    mod.error = 'pgdb.dothing('+str(type(mod.withx))+str(mod.withx)+') failed with: WTF???'

...因为那真的...有点烂。

如果是这样的话,有没有其他方法可以捕获所有类型的所有异常并为它们获取错误消息?看起来这将是非常非常理想的事情(而且似乎单线应该解决它,它应该看起来有点像前一个例子,而不是后者。)

请在回答之前:是的,我知道 Python 2.2.2 已经过时了。不,它不会很快升级。这是一个拥有数百万行代码的生产系统;它是稳定的,我们希望它保持这种状态,基于“不损坏,不修复”。

我只需要对我遇到的异常过程的这一部分有充分的了解。所有的解释似乎都是对我所知道的……乐观的假设。 :)

感谢您的任何见解。

【问题讨论】:

    标签: python exception-handling


    【解决方案1】:

    试试这个,虽然这是一个不好的做法。覆盖错误时应尽可能明确。

    try:
        ...
    except:
        e = sys.exc_info()
        print e
    

    我也建议看看https://wiki.python.org/moin/HandlingExceptions

    【讨论】:

    • “我也建议你看看……”我做到了。这就是我得到关于除了不总是来自异常的引用的地方。看起来你上面的答案符合我的要求。非常感谢。另外,我没有覆盖错误。我正试图找出错误是什么,因为当它发生时我不在那里,一般来说,我需要捕获它并将它提供给我自己和用户,至少以某种形式。跨度>
    • @fyngyrz,没问题。也没有冒犯的意思,我只是喜欢用我的答案链接到文档。如果我的回答对您有所帮助,为什么不考虑点击左侧的复选标记? :-)
    【解决方案2】:

    哇。解开这个问题中的一些错误假设需要一些时间。

    捕捉一切是不可取的。怎么会这样?如果引发异常,那是因为出现了问题。你不可能编写代码来处理所有可能发生的错误,仅仅因为没有代码是完美的。因此,当发生不可预见的错误时会引发异常,并且您为知道可以处理的错误编写处理代码。

    但这仍然留下您无法处理的事情:您为什么要抓住那些?你会怎么做,抓住他们?说“我将记录它们并继续”是没有意义的,因为现在您的系统处于未定义状态。那条数据存在吗?不知道。它是否已写入数据库?说不出来。您刚刚损失了数百万的收入吗?找我,老大。

    关于 Python 版本,如果您在不受支持的平台上运行生产系统,在该平台上不仅发现了大量严重漏洞,而且实际利用了这一事实,这不算“破坏”,那么我不不知道是什么。

    【讨论】:

    • 捕获它们的目的是让上层可以将该错误传递给正在盯着网络浏览器的用户,并且不会被来自网络的消息所启发CGI 向北运行的浏览器,并通知 IT。我可以至少说“数据库操作失败”,因此您的会话已关闭。已通知 IT 部门。”您对“catch”=“carry on 不管”的假设是错误的。关于您对漏洞的假设,这些系统不在 WAN 上。如果您真的回答了这个问题而不是调用 snark(MAX)
    • 这实际上并没有回答问题。这是一个评论,虽然是一个复杂的评论。
    【解决方案3】:

    查看sys.exc_info() 以在您的普通execpt: 子句中获取异常信息。

    【讨论】:

    • 谢谢。这是其中的一部分,好吧,但是 sys.exc_info() 返回 (,,) 以表示查询格式错误,而 Exception,e 返回特定的错误。所以两者都是:except:Exception,e:后跟except:并从sys.exc_info()中捕获
    • 关于更长的答案比我的要好得多,您当然是对的。但是您对 sys.exc_info() 返回的内容是错误的。 Python 中不存在像 (,,) 这样的值。它应该是正确的值三元组(异常类型、异常实例、回溯)。如果您得到(,,) 的输出,这可能是由于您使用了一些不寻常的前端。
    • 有趣。我知道的唯一前端是 PGDB。当我捕捉到异常时,e: 我得到了预期的值。当我捕获除:仅,然后 e=sys.exc_info() 时,我得到的打印结果为“(,,)”它也可能是早期 python 的产物或其他东西。我会编写一些测试用例,这很容易做到。下一条评论很快。
    • 好的,这很奇怪。得到了你描述的结果。没有空的看起来像元组的东西。我什至以同样的方式引发了错误(将查询中的列名更改为不存在的列),只是删除了 Exception,e: catch in a test copy in the db utes 模块,因此它会落入 sys.机制。好吧,你显然是对的,我显然是错的,但我确实看到了我所描述的。我得考虑一下。一定是在某处做错了什么。这当然是可能的。感谢您的澄清。给你一个“向上”。 :)
    猜你喜欢
    • 1970-01-01
    • 2011-02-03
    • 2021-11-14
    • 1970-01-01
    • 2014-01-25
    • 2012-03-12
    • 2019-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多