ホームページ  >  記事  >  バックエンド開発  >  知識を増やしましょう! Pythonの例外情報もこんな感じで表示できます

知識を増やしましょう! Pythonの例外情報もこんな感じで表示できます

王林
王林転載
2023-04-11 16:40:031758ブラウズ

知識を増やしましょう! Pythonの例外情報もこんな感じで表示できます

はじめに

日々の開発では、ほとんどの時間はトレースバック モジュール情報の読み取りとコードのデバッグに費やされます。この記事では、プロンプト情報をより簡潔かつ正確にするためにトレースバック モジュールを改善します。

この目的に基づいて、例外フック (例外処理フック) をカスタマイズして、トレースバック内の冗長な情報を削除し、エラーの解決に必要な内容のみを残します。さらに、いくつかの便利なサードパーティ ライブラリも紹介します。これらのライブラリの例外フックを直接使用して、トレースバック モジュールを簡素化できます。

例外フック

プログラムの例外情報が 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 属性を使用して変数をコンソールに出力することもでき、コードのデバッグに役立ちます。

トレースバック オブジェクトを使用して例外情報を出力することもできますが、手間がかかり、出力情報も読みにくくなります。より便利なアプローチは、例外情報を抽出するための多くの組み込み補助関数を備えたトレースバック モジュールを使用することです。

例外フックの基本的な知識を紹介しました。次に、例外フックをカスタマイズし、いくつかの実用的な機能を追加します。

#カスタマイズされた例外フック


    例外情報をファイルに自動的に保存し、後でコードをデバッグするときに表示することもできます。
  1. 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")
    例外情報はデフォルトで stderr に保存されます。保存場所を変更したい場合は、次のようにすることができます:
  1. 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
    プロンプト情報の特定の部分 カラーを設定:
  1. # 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}")
上記で紹介した例に加えて、各フレームのローカル変数を出力したり、例外が発生した行で参照されている変数を検索したりすることもできます。 。これらの例外フックはすでに非常に成熟しているため、カスタム例外フックと比較して、他の開発者のソース コードを読んで、その設計アイデアを学ぶことをお勧めします。


# 各フレームのローカル変数を出力[1]
  • 例外が発生した行で参照されている変数を検索[2]

  • サードパーティ ライブラリの例外フック


例外フックをカスタマイズするのは興味深いことですが、多くのサードパーティ ライブラリはすでにこの機能を実装しています。車輪を再発明するのではなく、他の優れたツールに目を向けてください。


まず第一に、私の個人的なお気に入りは Rich です。これは、pip で直接インストールし、インポートして使用できます。 1 つの例でのみ使用したい場合は、次のようにすることができます: python -m rich.traceback
  1. # 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

知識を増やしましょう! Pythonの例外情報もこんな感じで表示できます

better_Exceptions も人気があるため、必要がありますまず環境変数 BETTER_EXCEPTIONS=1 を設定し、pip でインストールします。さらに、TERM 変数が xterm ではない場合は、SUPPORTS_COLOR を True に設定します。
  1. # 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

知識を増やしましょう! Pythonの例外情報もこんな感じで表示できます

使用するのに最も便利なライブラリは pretty_errors です。これをインポートするだけです:
  1. # 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()
  2. 直接インポートに加えて、 , 上記のコードには、ライブラリのオプションの構成もいくつか示されています。その他の設定はここで確認できます: 設定 [3]


知識を増やしましょう! Pythonの例外情報もこんな感じで表示できます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()
  1. stackprinter库
# https://github.com/cknd/stackprinter
# pip install stackprinter
import stackprinter
stackprinter.set_excepthook(style='darkbg2')
do_stuff()

知識を増やしましょう! Pythonの例外情報もこんな感じで表示できます

结论

本文我们学习了如何自定义Exception Hooks,但我更推荐使用第三方库。你可以在本文介绍的第三方库中任选一个喜欢的,用到项目中。需要注意的是使用自定义Exception Hooks可能会丢失某些关键信息,例如:本文中的某些例子中,输出中缺少文件路径,在远程调试代码这无疑很不方便,因此,需要谨慎使用。

以上が知識を増やしましょう! Pythonの例外情報もこんな感じで表示できますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事は51cto.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。