【问题标题】:Coloring exceptions from Python on a terminal在终端上为 Python 着色异常
【发布时间】:2013-02-08 15:30:30
【问题描述】:

有没有一种简单的方法可以让异常的消息在命令行上着色?例如

def g():    f()
def f():    1/0
g()

给出错误

Traceback (most recent call last):
  File "test.py", line 3, in <module>
    g()
  File "test.py", line 1, in g
    def g():    f()
  File "test.py", line 2, in f
    def f():    1/0
ZeroDivisionError: integer division or modulo by zero

我希望在终端上对“整数除法或模除以零”进行着色或突出显示,以便我可以快速从长追溯中找出它(仅限 Linux)。理想情况下,我不想为每个异常编写一个自定义类,而是以某种方式捕获并格式化所有类型。

编辑: cmets 中链接的问题提供了有关如何使用外部 软件解决问题的示例,但我对内部 Python 解决方案感兴趣。

【问题讨论】:

  • @MartijnPieters 里面有很多很好的信息,我可能会用到,但它们似乎都涉及 python 的解决方案 outside,即在代码完成后突出显示被运行。我正在寻找做一些内部的事情(我会相应地编辑问题)。
  • 你必须连接你自己的异常处理程序,然后可能通过 pygments 运行回溯。
  • @MartijnPieters 你刚才说的大概就是我要问的。我不确定我会怎么做。
  • 如果您使用的终端支持它,也许您可​​以在异常消息中嵌入ANSI escape sequences。可能有一个模块。
  • 这是table 的 ANSI 转义序列——很多人甚至不需要模块来完成它。

标签: python exception colors


【解决方案1】:

您可以将自定义函数分配给sys.excepthook handler。每当有 unhandled 异常(即退出解释器的异常)时,都会调用该函数。

def set_highlighted_excepthook():
    import sys, traceback
    from pygments import highlight
    from pygments.lexers import get_lexer_by_name
    from pygments.formatters import TerminalFormatter

    lexer = get_lexer_by_name("pytb" if sys.version_info.major < 3 else "py3tb")
    formatter = TerminalFormatter()

    def myexcepthook(type, value, tb):
        tbtext = ''.join(traceback.format_exception(type, value, tb))
        sys.stderr.write(highlight(tbtext, lexer, formatter))

    sys.excepthook = myexcepthook

set_highlighted_excepthook()

此版本使用 pygments library 将回溯文本转换为使用 ANSI 着色格式的文本,然后将其写入 stderr

有人把它变成了一个可以检测终端支持并让你设置 pygments 样式的项目,参见colored-traceback.py

【讨论】:

  • 回溯的哪些部分将被突出显示,全部?
  • @martineau:全部。您必须调整词法分析器的配置和/或更改您传入的内容以使其突出显示更少的内容。
  • 要获得pygments,我只需要从任意目录获取$ easy_install Pygments
  • 这不会着色语法错误(缩进错误等)。有没有办法给这些上色?
  • @frederick99 语法错误也是回溯,但如果错误在设置挂钩的文件中或导入设置挂钩的模块,则没有挂钩来拦截回溯。在导入有错误的文件时会引发语法错误异常(因为这会触发编译)。
【解决方案2】:

这采用了@freakish 共享的解决方案,并使着色成为异常的一部分,而不是要求用户为每个异常消息添加颜色。显然,它只适用于自定义异常,所以它可能不是 OP 想要的。

from colorama import Fore, init
init()

class Error (Exception):
    def __init__ (self, message):
        super().__init__(Fore.RED + message)

class BadConfigFile (Error):
    pass

raise BadConfigFile("some error message")

这将以红色打印带有“一些错误消息”的回溯。将“错误”作为基类意味着您可以创建其他将全部继承消息颜色的异常。

【讨论】:

    【解决方案3】:

    使用 IPython 模块找到了另一种方法,这可能是每个人都已经安装的依赖项:

    from IPython.core.ultratb import ColorTB
    c = ColorTB()
    exc = sys.exc_info()
    print(''.join(c.structured_traceback(*exc)))
    

    【讨论】:

    • 应该使用ColorTB().text(*exc)而不是手动加入字符串,因为如果ColorTB设置为'plain'以外的其他模式,手动加入将不起作用。
    【解决方案4】:

    查看colorama(或任何其他着色)模块。然后你可以用以下方式包装你的整个应用程序:

    import traceback
    from colorama import Fore, init
    init( )
    
    try:
        // your app
    except Exception:
        print Fore.RED + traceback.format_exc( ) + Fore.RESET
        // possibly raise again or log to db
    

    【讨论】:

    • 有趣,感谢您的回答。在 try 块中不缩进“我的应用程序”是否有可能?
    • @Hooked 我不这么认为。但这是一个问题吗?将您的整个应用程序放在一个函数中,然后调用该函数并使用 try:except 块包装该函数。如果涉及线程,它可能会更复杂。
    • 您可以使用sys.excepthook 来避免整个应用程序周围的try:except 块,如Martijn Pieters 的回答中所述。
    猜你喜欢
    • 2012-04-04
    • 2012-11-21
    • 1970-01-01
    • 2014-09-26
    • 1970-01-01
    • 1970-01-01
    • 2017-06-06
    • 1970-01-01
    • 2022-07-07
    相关资源
    最近更新 更多