如何在Gnome终端中为Python错误输出上色?

14 投票
4 回答
7902 浏览
提问于 2025-04-18 15:51

注意:我在研究了如何实现这个之后才问这个问题。其他一些看起来相似但实际上和我问题不同的内容包括:

  1. 在python脚本中进行颜色编码
  2. 在脚本中导入颜色库
  3. 使用像Solarized这样的工具来改善Vim等工具的python代码颜色编码。

我想要的是什么: 我已经有一个简单的python脚本(比如说,test.py),我是在Gnome终端中执行它的。

python test.py

test.py会在终端中输出一些错误信息。 错误示例:

Traceback (most recent call last):
  File "test.py", line 2, in <module>
    with open('', 'rb') as csvfile:
IOError: [Errno 2] No such file or directory: ''

我希望错误的关键词能用粗体红色显示,比如行号用特定的颜色,这样更容易找到错误。

正如你所看到的,Stackoverflow已经很好地进行了错误的颜色编码。而在我的Gnome终端中,输出是单一颜色的。我该如何在终端中获得这样漂亮的颜色编码输出呢?

4 个回答

0

顺便说一下,你可以把脚本放在一个叫 main 的函数里,然后在一个 try ... except 块中调用这个 main 函数,这样可以捕捉到错误信息,把它上色后打印出来。

要获取错误信息,你需要调用 sys.exc_info。然后,使用 traceback.format_exception 来格式化堆栈跟踪和异常信息。通过一些基本的正则表达式,你可以把每个 ..Err.. 包裹在 \033[91m...Err...\033[0m 里,这样就能把颜色变成红色:

def main():
   with open('xxx.txt', 'r') as fin:
        return fin.read()

try:
    main()
except:
    import re
    from sys import exc_info
    from traceback import format_exception

    RED, REV = r'\033[91m', r'\033[0m'
    err = ''.join(format_exception(*exc_info()))
    print(re.sub(r'(\w*Err\w*)', RED + r'\1' + REV, err))

结果:

err

1

这是一个快速的解决办法,只适用于UNIX系统。你可以把标准输出(也就是程序的输出信息)重定向到一个以.py结尾的文件里。然后用vimcat这个工具来显示这个文件,这样输出会有颜色,看起来更好。最后,把这些步骤放在一个shell函数里。比如在bash中可以这样做;

# print colorised python output
colorized() {
    local out='out.py'
    if (( $# < 1)) 
    then
        printf "Usage: %s pyhon-script\n" $0 >&2
        return 1;
    fi
    if [ -e $out ]; 
    then
        rm $out
    fi
    python $@ 2> $out
    empty=$(stat $out | grep empty)
    if (( $? == 1 ))
    then
        vimcat $out
    fi
}
8

[注意:颜色在2021年12月7日更新,以便更易阅读 :)]

注意:这并没有直接回答上面的问题,因为我对 sed 不太擅长。但这提高了可读性,相比其他需要安装ipython或运行较慢的方式,这其实是我常用的方法。

当前(轻量级解决方案——也就是说,不需要安装任何东西,也不需要逐个编辑现有的python文件)

根据 https://stackoverflow.com/a/20910449,我们来使用 sed 和 ANSI 颜色代码。

添加到 ~/.bashrc

norm="$(printf '\033[0m')" #returns to "normal"
bold="$(printf '\033[0;1m')" #set bold
red="$(printf '\033[0;31m')" #set red
boldyellowonblue="$(printf '\033[0;1;33;44m')" 
boldyellow="$(printf '\033[0;1;33m')"
boldred="$(printf '\033[0;1;31m')" #set bold, and set red.

copython() {
        python $@ 2>&1 | sed -e "s/Traceback/${boldyellowonblue}&${norm}/g" \
        -e "s/File \".*\.py\".*$/${boldyellow}&${norm}/g" \
        -e "s/\, line [[:digit:]]\+/${boldred}&${norm}/g"
    }

重新加载

$ source ~/.bashrc

原本的样子

$ python main.py

未着色的python错误信息

看起来真让人烦,读起来很费劲。现在对比一下

$ copython main.py

[着色的python错误信息

虽然颜色有点刺眼,但我觉得还不错,而且我不太懂ANSI代码,所以这些颜色我就只能用这些了 :)


颜色更新为更悦目 [2021年12月7日]

# ---
# Color python error output
# ---

norm="$(printf '\033[0m')" #returns to "normal"
bold="$(printf '\033[0;1m')" #set bold
red="$(printf '\033[0;31m')" #set red
boldyellowonblue="$(printf '\033[0;1;33;44m')" #set blue bkgrd, bold yellow text
boldyellow="$(printf '\033[0;1;33m')" #set gold yellow text
boldred="$(printf '\033[0;1;31m')" #set bold red

# Color error messages from python, use as "copython test.py" instead of "python test.py"
# WARNING: Takes time to run (small but noticeable)
# May also interfer with print to console (for long running programs) 
copython() {
    python $@ 2>&1 | sed -e "s/Traceback/${boldyellowonblue}&${norm}/g" \
        -e "s/File \".*\.py\".*$/${bold}&${norm}/g" \
        -re "s/\, line [0-9]\+/${boldred}&${norm}/g" \
        -re "s/ {4}(.*)$/${boldyellow}&${norm}/g" \ 
        -e "s/.*Error:.*$/${boldred}&${norm}/g" \
    }

着色的python输出


关于ANSI颜色代码的说明

注意 \033[ 表示代码的开始,这让我更好地理解了发生了什么。

0m # normal
0;1m # bold 
0;1;33;44m # bold yellow on blue 
0;1;33m # bold yellow 
0;1;31m # bold red

所以我猜第一个 1 表示加粗,第二个 33 表示前景色,第三个 44 表示背景色。大概是这样的。


过时

我也在寻找一种不需要修改每一个想要打印错误信息的python文件的方法。如何使用 Tobin 的回答对我来说并不是很清楚。

对于那些想知道如何使用的人,需要安装 vimcat,然后将上面的函数添加到bashrc(或其他你引用的文件)中,接着运行 $ colorized test.py(而不是 $ python test.py

例如

~$ wget https://raw.githubusercontent.com/vim-scripts/vimcat/master/vimcat vimcat
~$ mv vimcat /usr/share/bin  # or /home/bin or wherever you want
~$ echo $PATH # make sure vimcat's directory is in your PATH variable, if not add to `~/.bashrc`
home/rui/.local/bin:/usr/local/sbin:/usr/share/bin
~$ source ~/.bashrc # reload PATH if had to add vimcat location
~$ vimcat somefile.sh # test that vimcat can be called
~$ colorized calibrate.py 

我之前和之后的样子: 前后对比

并验证vimcat是否正常工作/是否已被正确引用:

vimcat

注意,这样运行确实会明显花费更多时间!

$ time colorized calibrate.py 
real    0m0.484s
user    0m0.392s
sys 0m0.085s

rui@chaiX1YG2:~$ $ time python calibrate.py 
real    0m0.343s
user    0m0.271s
sys 0m0.072s
14

你可以使用IPython的颜色功能。只需要在你程序的开头加上这一行代码。这样一来,所有的错误都会由ultratb来处理,并且会以彩色显示,同时还会展示出导致错误的代码片段中的局部变量值。

import sys
from IPython.core import ultratb
sys.excepthook = ultratb.FormattedTB(color_scheme='Linux', call_pdb=False)

即使你用普通的Python解释器来运行你的脚本,这个功能也能正常工作。

撰写回答