日々の開発では、ほとんどの時間はトレースバック モジュール情報の読み取りとコードのデバッグに費やされます。この記事では、プロンプト情報をより簡潔かつ正確にするためにトレースバック モジュールを改善します。
この目的に基づいて、例外フック (例外処理フック) をカスタマイズして、トレースバック内の冗長な情報を削除し、エラーの解決に必要な内容のみを残します。さらに、いくつかの便利なサードパーティ ライブラリも紹介します。これらのライブラリの例外フックを直接使用して、トレースバック モジュールを簡素化できます。
プログラムの例外情報が try/catch によってキャプチャされない場合、Python インタープリターは sys.excecthook() 関数を呼び出します。タイプ、値、トレースバックの 3 つのパラメータをそれぞれ受け取ります。この関数は例外フックとも呼ばれ、プログラムの例外情報を出力します。
次の例を見てみましょう:
import sys def exception_hook(exc_type, exc_value, tb): print('Traceback:') filename = tb.tb_frame.f_code.co_filename name = tb.tb_frame.f_code.co_name line_no = tb.tb_lineno print(f"File {filename} line {line_no}, in {name}") # Exception type 和 value print(f"{exc_type.__name__}, Message: {exc_value}") sys.excepthook = exception_hook
この例では、トレースバック (tb) オブジェクトから例外情報が発生した場所を取得できます。ファイル名 (f_code.co_filename)、関数/モジュール名 (f_code.co_name)、および行番号 (tb_lineno) が含まれます。さらに、exc_type 変数と exc_value 変数を使用して、例外情報の内容を取得できます。
エラーを生成する関数を呼び出すと、Exception_hook は次の内容を出力します:
def do_stuff(): # 写一段会产生异常的代码 raise ValueError("Some error message") do_stuff() # Traceback: # File /home/some/path/exception_hooks.py line 22, in <module> # ValueError, Message: Some error message
上記の例は例外情報の一部を提供しますが、必要な情報を取得するためにコードをデバッグするための情報 すべての情報、および例外の時間と場所がわかっている場合は、トレースバック オブジェクトについても詳しく調べる必要があります。
def exception_hook(exc_type, exc_value, tb): local_vars = {} while tb: filename = tb.tb_frame.f_code.co_filename name = tb.tb_frame.f_code.co_name line_no = tb.tb_lineno print(f"File {filename} line {line_no}, in {name}") local_vars = tb.tb_frame.f_locals tb = tb.tb_next print(f"Local variables in top frame: {local_vars}") ... # File /home/some/path/exception_hooks.py line 41, in <module> # File /home/some/path/exception_hooks.py line 7, in do_stuff # Local variables in top frame: {'some_var': 'data'}
上記の例からわかるように、トレースバック オブジェクト (tb ) は本質的にリンクされたリストであり、発生したすべての例外を保存します。したがって、 tb_next を使用して tb を走査し、各例外情報を出力できます。これに基づいて、tb_frame.f_locals 属性を使用して変数をコンソールに出力することもでき、コードのデバッグに役立ちます。
トレースバック オブジェクトを使用して例外情報を出力することもできますが、手間がかかり、出力情報も読みにくくなります。より便利なアプローチは、例外情報を抽出するための多くの組み込み補助関数を備えたトレースバック モジュールを使用することです。
例外フックの基本的な知識を紹介しました。次に、例外フックをカスタマイズし、いくつかの実用的な機能を追加します。
LOG_FILE_PATH = "./some.log" FILE = open(LOG_FILE_PATH, mode="w") def exception_hook(exc_type, exc_value, tb): FILE.write("*** Exception: ***n") traceback.print_exc(file=FILE) FILE.write("n*** Traceback: ***n") traceback.print_tb(tb, file=FILE) # *** Exception: *** # NoneType: None # # *** Traceback: *** # File "/home/some/path/exception_hooks.py", line 82, in <module> # do_stuff() # File "/home/some/path/exception_hooks.py", line 7, in do_stuff # raise ValueError("Some error message")
import logging logging.basicConfig( level=logging.CRITICAL, format='[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', datefmt='%H:%M:%S', stream=sys.stdout ) def exception_hook(exc_type, exc_value, exc_traceback): logging.critical("Uncaught exception:", exc_info=(exc_type, exc_value, exc_traceback)) # [17:28:33] {/home/some/path/exception_hooks.py:117} CRITICAL - Uncaught exception: # Traceback (most recent call last): # File "/home/some/path/exception_hooks.py", line 122, in <module> # do_stuff() # File "/home/some/path/exception_hooks.py", line 7, in do_stuff # raise ValueError("Some error message") # ValueError: Some error message
# pip install colorama from colorama import init, Fore init(autoreset=True)# Reset the color after every print def exception_hook(exc_type, exc_value, tb): local_vars = {} while tb: filename = tb.tb_frame.f_code.co_filename name = tb.tb_frame.f_code.co_name line_no = tb.tb_lineno # Prepend desired color (e.g. RED) to line print(f"{Fore.RED}File {filename} line {line_no}, in {name}") local_vars = tb.tb_frame.f_locals tb = tb.tb_next print(f"{Fore.GREEN}Local variables in top frame: {local_vars}")
# https://rich.readthedocs.io/en/latest/traceback.html # pip install rich # python -m rich.traceback from rich.traceback import install install(show_locals=True) do_stuff()# Raises ValueError
# https://github.com/Qix-/better-exceptions # pip install better_exceptions # export BETTER_EXCEPTIONS=1 import better_exceptions better_exceptions.MAX_LENGTH = None # 检查你的 TERM 变量是否被设置为 `xterm`, 如果没有执行以下操作 # See issue: https://github.com/Qix-/better-exceptions/issues/8 better_exceptions.SUPPORTS_COLOR = True better_exceptions.hook() do_stuff()# Raises ValueError
# https://github.com/onelivesleft/PrettyErrors/ # pip install pretty_errors import pretty_errors # 如果你对默认配置满意的话,则无需修改 pretty_errors.configure( filename_display= pretty_errors.FILENAME_EXTENDED, line_number_first = True, display_link= True, line_color= pretty_errors.RED + '> ' + pretty_errors.default_config.line_color, code_color= '' + pretty_errors.default_config.line_color, truncate_code = True, display_locals= True ) do_stuff()
IPython の Ultratb モジュール
# https://ipython.readthedocs.io/en/stable/api/generated/IPython.core.ultratb.html # pip install ipython import IPython.core.ultratb # Also ColorTB, FormattedTB, ListTB, SyntaxTB sys.excepthook = IPython.core.ultratb.VerboseTB(color_scheme='Linux')# Other colors: NoColor, LightBG, Neutral do_stuff()
# https://github.com/cknd/stackprinter # pip install stackprinter import stackprinter stackprinter.set_excepthook(style='darkbg2') do_stuff()
本文我们学习了如何自定义Exception Hooks,但我更推荐使用第三方库。你可以在本文介绍的第三方库中任选一个喜欢的,用到项目中。需要注意的是使用自定义Exception Hooks可能会丢失某些关键信息,例如:本文中的某些例子中,输出中缺少文件路径,在远程调试代码这无疑很不方便,因此,需要谨慎使用。
以上が知識を増やしましょう! Pythonの例外情報もこんな感じで表示できますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。