How to colorize the output of Python errors in the Gnome terminal?

前端 未结 4 1407
难免孤独
难免孤独 2021-02-09 19:17

Note: I am asking this question after researching how to actually do it. Other questions which are somewhat similar, but actually differ from my question relate to:

    <
相关标签:
4条回答
  • 2021-02-09 19:32

    Quick hack solution, UNIX only. Redirect stdout to a file with .py suffix. Then display file using vimcat for colorised output. Wrap this all up in a shell function. For example in 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
    }
    
    0 讨论(0)
  • 2021-02-09 19:37

    Current (lightweight solution -- as in, don't need to install anything, and don't have to edit existing python files one-by-one)

    As per, https://stackoverflow.com/a/20910449, let's use sed and ANSI color codes.

    Add to ~/.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"
        }
    

    Reload

    $ source ~/.bashrc

    What it looks like originally

    $ python main.py

    Pretty annoying to read. Now compare with

    $ copython main.py

    It's a bit garish but I'm happy with it, and I don't understand ANSI codes so these are the colors I'm stuck with :)


    Note on ANSI Color Code

    Note that \033[ marks the beginning of a code, which helped me understand a bit better what is going on.

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

    So I guess the first 1 indicates bold, then the second 33 indicates foreground color, and the third 44 indicates background color. Something like that.


    Obsolete

    I was also looking for something where I didn't need to modify every single python file I want to print error messages from. How to use Tobin's answer wasn't immediately clear to me.

    For those wondering how to use, need to install vimcat, then add above function to bashrc (or other file that you source), and run $ colorized test.py (instead of $ python test.py)

    For instance

    ~$ 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 
    

    What before and after looks like for me:

    And verifying that vimcat works / has been sourced properly:

    Note that this does take noticeably more time to run!

    $ 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
    
    0 讨论(0)
  • 2021-02-09 19:47

    FWIW, you can wrap the script in a main function, and call the main function within a try ... except block, get the error message, colourize it and print it;

    To get the error message you need a call to sys.exc_info. traceback.format_exception formats the stack-trace and the exception information. Using basic regex you can wrap every ..Err.. inside a \033[91m...Err...\033[0m which turns the colour into red:

    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))
    

    Result:

    err

    0 讨论(0)
  • 2021-02-09 19:50

    You could use the IPython coloring. Just put this at the beginning of your program. Every exception will be then handled by ultratb and be displayed in color and also show the locals() values for the code snippet that made the exception.

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

    This will work even if you invoke your script with the vanilla python interpreter.

    0 讨论(0)
提交回复
热议问题