Исключение цвета из Python на терминале
Есть ли простой способ получить сообщение о том, что исключение будет окрашено в командной строке? Например
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). В идеале я бы не хотел писать пользовательский класс для каждого Exception, но каким-то образом улавливал и форматировал все виды.
EDIT: Вопрос, связанный с комментариями, содержит примеры того, как решить проблему с внешним программным обеспечением, но меня интересует внутреннее решение Python.
Ответы
Ответ 1
Вы можете назначить пользовательскую функцию обработчику sys.excepthook
. Функция вызывается всякий раз, когда есть необработанное исключение (например, выходящее из интерпретатора).
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
для преобразования текста трассировки в текст, отформатированный с раскраской ANSI, перед записью его в stderr
.
Кто-то превратил это в проект, который обнаруживает поддержку терминала и позволяет вам установить стиль фрагментов, см. colored-traceback.py
.
Ответ 2
Найден другой способ сделать это с помощью модуля IPython, который, скорее всего, зависит от того, что все уже установлены:
from IPython.core.ultratb import ColorTB
c = ColorTB()
exc = sys.exc_info()
print(''.join(c.structured_traceback(*exc)))
Ответ 3
Посмотрите 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
Ответ 4
Это принимает решение @freakish shared и делает раскраску частью исключения, а не требует от пользователя добавлять цвет к каждому сообщению исключения. Очевидно, что он работает только для пользовательских исключений, поэтому он может быть не совсем тем, что искал 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")
Это напечатает трассировку с "некоторым сообщением об ошибке" красным. Наличие "Error" в качестве базового класса означает, что вы можете создавать другие исключения, которые будут наследовать раскраску сообщения.