将格式化异常像Python一样显示

20

如果我在Python中引发一个异常,这是我得到的结果:

raise Exception("Hello world")
Traceback (most recent call last):

  File "<ipython-input-24-dd3f3f45afbe>", line 1, in <module>
    raise Exception("Hello world")

Exception: Hello world

注意最后一行写着Exception: Hello world。假设有一个异常(foo = Exception("Hello world")),我该如何产生类似这样的文本?以下任何一种方法都无法实现:

str(foo)
Out[27]: 'Hello world'

repr(foo)
Out[28]: "Exception('Hello world',)"

"{}".format(foo)
Out[29]: 'Hello world'

"{}: {}".format(type(foo), foo)
Out[30]: "<type 'exceptions.Exception'>: Hello world"

为什么你需要这样做? - OneCricketeer
1
为什么不直接使用'Exception: {}'.format(foo)呢? - Anton Protopopov
1
@cricket_007,我正在一个上下文中工作,在这个上下文中,写入控制台的输出可能不会被看到,因此我想捕获异常,在消息框中显示它,并以漂亮的格式显示(在我的情况下使用EasyGUI),然后再次引发它。 - kuzzooroo
1
@AntonProtopopov,实际使用中异常会有更多有趣的类型(比如KeyError),我想显示该类型而不仅仅是将所有内容标记为异常。 - kuzzooroo
4
在异常处理程序中调用traceback.format_exc()可以获取与Python打印相同的信息。 - tdelaney
2个回答

17
如果您的异常对象为exc,那么:
  • 冒号前面的部分是type(exc).__name__
  • 冒号后面的部分是str(exc)
因此,您可以这样做:
print('{}: {}'.format(type(exc).__name__, exc))

谢谢。很遗憾的是,在dir(type(foo))中找不到__name__,否则我可能会发现这个问题。 - kuzzooroo
这个文档在此有记录(向下滚动一点...) - Kevin

14

将tdelaney的答案形式化并展示区别...

字符串

#test.py
import traceback

try :
    raise TypeError("Wrong Type baby!")

except Exception as e:
    print( "EXCEPTION FORMAT PRINT:\n{}".format( e ) )
    print( "EXCEPTION TRACE  PRINT:\n{}".format( "".join(traceback.format_exception(type(e), e, e.__traceback__))

输出结果

EXCEPTION FORMAT PRINT:
Wrong Type baby!
EXCEPTION TRACE  PRINT:
Traceback (most recent call last):
  File "test.py", line 4, in <module>
    raise TypeError("Wrong Type baby!")
TypeError: Wrong Type baby!

日志记录

如果您正在处理日志记录,还可以使用exception方法和exc_info关键字参数来为您进行格式化。需要注意的是,在根记录器将警告作为其默认日志级别时,调试和信息级别的日志消息会被忽略。

# logTest.py
import logging

try :
    raise ValueError("my bad value")
except Exception as e :
    logging.exception( e )
    logging.debug("\n{}\nDEBUG LEVEL EXAMPLE".format('-'*30), exc_info=e)
    logging.info("\n{}\nINFO LEVEL EXAMPLE".format('-'*30), exc_info=e)
    logging.warning("\n{}\nWARNING LEVEL EXAMPLE".format('-'*30), exc_info=e)
    logging.error("\n{}\nERROR LEVEL EXAMPLE".format('-'*30), exc_info=e)

通过控制台输出结果...

ERROR:root:my bad value
Traceback (most recent call last):
  File "/Users/me/logTest.py", line 5, in <module>
    raise ValueError("my bad value")
ValueError: my bad value
WARNING:root:
------------------------------
WARNING LEVEL EXAMPLE
Traceback (most recent call last):
  File "/Users/me/logTest.py", line 5, in <module>
    raise ValueError("my bad value")
ValueError: my bad value
ERROR:root:
------------------------------
ERROR LEVEL EXAMPLE
Traceback (most recent call last):
  File "/Users/me/logTest.py", line 5, in <module>
    raise ValueError("my bad value")
ValueError: my bad value

@Jarrad,你用的是哪个版本的Python 3?我刚在3.7.3上运行了这个程序。 - jxramos
1
字符串部分,而不是日志记录部分。 - Jarrad
看起来 traceback.format_exc() 不会将异常作为对象处理,然而 traceback.format_exception() 会。你能更新一下代码示例吗? - Scott H
@ScottH 我刚刚才意识到,那个例子确实是有问题的。我不确定它曾经在哪个版本的Python上运行过。 - jxramos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接