【问题标题】:How in Python find where exception was raised如何在 Python 中找到引发异常的位置
【发布时间】:2014-04-09 13:03:53
【问题描述】:

如何确定在哪个函数中引发了异常。例如存在两个函数:'foo'和'bar'。在 'foo' 中会随机引发异常。

import random


def foo():
    if random.randint(1, 10) % 2:
        raise Exception
    bar()


def bar():
    raise Exception

try:
    foo()
except Exception as e:
    print "Exception raised in %s" % ???

【问题讨论】:

  • 如果这是一个纯粹的“学术”问题,为什么不呢,但你不应该依赖于检查现实代码中的堆栈跟踪之类的东西......而不是使用自定义异常类(或其中一个许多内置的)更好。
  • 是的,只是很有趣

标签: python exception


【解决方案1】:
import inspect

try:
    foo()
except Exception as e:
    print "Exception raised in %s" % inspect.trace()[-1][3]

【讨论】:

  • 这可能是提问者的意思,但它可能不是现实生活中最好的解决方案:)
【解决方案2】:

我使用 traceback 模块,如下所示:

import traceback

try:
    1 / 0
except Exception:
    print traceback.format_exc()

这给出了以下输出:

Traceback (most recent call last):
  File "<ipython-input-3-6b05b5b621cb>", line 2, in <module>
    1 / 0
ZeroDivisionError: integer division or modulo by zero

如果代码从文件中运行,回溯将告诉错误发生的行和字符号:)

编辑:

容纳Habibutsu的评论:Yes, it's useful for printing, but when needed to get more info (for example function name) - not suitable

文档页面告诉您如何以编程方式提取跟踪:http://docs.python.org/2/library/traceback.html

从上面链接的页面:

>>> import traceback
>>> def another_function():
...     lumberstack()
...
>>> def lumberstack():
...     traceback.print_stack()
...     print repr(traceback.extract_stack())
...     print repr(traceback.format_stack())
...
>>> another_function()
  File "<doctest>", line 10, in <module>
    another_function()
  File "<doctest>", line 3, in another_function
    lumberstack()
  File "<doctest>", line 6, in lumberstack
    traceback.print_stack()
[('<doctest>', 10, '<module>', 'another_function()'),
 ('<doctest>', 3, 'another_function', 'lumberstack()'),
 ('<doctest>', 7, 'lumberstack', 'print repr(traceback.extract_stack())')]
['  File "<doctest>", line 10, in <module>\n    another_function()\n',
 '  File "<doctest>", line 3, in another_function\n    lumberstack()\n',
 '  File "<doctest>", line 8, in lumberstack\n    print repr(traceback.format_stack())\n']

traceback.extract_stack 的文档字符串与 traceback.extract_tb 的文档字符串相同

traceback.extract_tb(traceback[, limit])

返回最多限制“预处理”堆栈跟踪条目的列表 从 traceback 对象中提取 traceback。它对 堆栈跟踪的替代格式。如果省略limit或None,则全部 条目被提取。 “预处理”的堆栈跟踪条目是 四元组(文件名、行号、函数名、文本)表示 通常为堆栈跟踪打印的信息。文字是 去除了前导和尾随空格的字符串;如果源 不可用,它是无。

【讨论】:

  • 是的,它对打印很有用,但是当需要获取更多信息(例如函数名称)时 - 不适合
  • @Habibutsu 我更新了我的答案,向您展示traceback 确实是合适的,并且可以用于提取函数名称例如:)
【解决方案3】:

你的目标是什么?如果您担心barfoo 抛出相同的异常类型而调用者无法区分它们,只需派生一个新的异常类即可:

import random

class FooException(Exception):
    """An exception thrown only by foo."""

def foo():
    if random.randint(1,10) % 2:
        raise FooException

    bar()

def bar():
    raise Exception

try:
    foo()
except FooException:
    print "Exception raised in foo..."
except:
    print "Exception raised in bar (probably)..."

【讨论】:

  • 我同意您的方法更好,但它不适用于您从用户那里收到的回调。或者例如 RPC 当 TypeError 可能被引发以尝试调用函数或在函数内部时。其实现在我并没有建立依赖这些信息的逻辑,但它很有趣。
  • 您可以将每个回调包装在引发自定义异常的代码中。
  • 在这种情况下,如果只是没有将其包含在新的异常中,则会丢失有关原始异常的信息
  • 好吧,如果你使用的是 Python 3,你可以使用exception chaining。在 Python 2 中执行此操作的方法不是很好。
猜你喜欢
  • 1970-01-01
  • 2019-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-28
  • 2023-03-14
  • 2018-12-24
  • 1970-01-01
相关资源
最近更新 更多