Dalam pembangunan harian, kebanyakan masa kita dihabiskan untuk membaca maklumat modul surih balik dan kod nyahpepijat. Dalam artikel ini, kami akan menambah baik modul jejak balik untuk menjadikan maklumat segera lebih ringkas dan tepat.
Berdasarkan tujuan ini, kami akan menyesuaikan Cangkuk Pengecualian (cangkuk pengendalian pengecualian) untuk mengalih keluar maklumat berlebihan dalam surih, hanya meninggalkan kandungan yang diperlukan untuk menyelesaikan ralat. Selain itu, saya juga akan memperkenalkan beberapa perpustakaan pihak ketiga yang berguna, dan anda boleh terus menggunakan Cangkuk Pengecualian di dalamnya untuk memudahkan modul jejak balik.
Jika maklumat pengecualian program tidak ditangkap melalui try/catch, penterjemah python akan memanggil fungsi sys.excepthook(), yang akan menerima 3 parameter, masing-masing: jenis, nilai, jejak balik. Fungsi ini juga dipanggil Exception Hook dan akan mengeluarkan maklumat pengecualian program.
Mari kita lihat contoh berikut:
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
Dalam contoh ini, kita boleh mendapatkan maklumat lokasi dan lokasi daripada objek jejak balik (tb). nama (f_code.co_filename), nama fungsi/modul (f_code.co_name), dan nombor baris (tb_lineno). Selain itu, kita boleh menggunakan pembolehubah exc_type dan exc_value untuk mendapatkan kandungan maklumat pengecualian.
Apabila kita memanggil fungsi yang menghasilkan ralat, exception_hook akan mengeluarkan kandungan berikut:
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
Contoh di atas menyediakan sebahagian daripada maklumat pengecualian, tetapi untuk mendapatkan kod penyahpepijatan, Semua maklumat yang diperlukan, dan untuk mengetahui masa dan lokasi pengecualian, kita juga perlu mengkaji objek jejak balik secara mendalam:
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'}
Seperti yang dapat dilihat daripada contoh di atas, objek jejak balik (tb) pada asasnya ialah senarai terpaut - Menyimpan semua pengecualian yang berlaku. Oleh itu, anda boleh menggunakan tb_next untuk melintasi tb dan mencetak maklumat setiap pengecualian. Atas dasar ini, anda juga boleh menggunakan atribut tb_frame.f_locals kepada pembolehubah output ke konsol, yang membantu menyahpepijat kod.
Adalah boleh menggunakan objek surih untuk mengeluarkan maklumat pengecualian, tetapi ia lebih menyusahkan Selain itu, maklumat output kurang boleh dibaca. Pendekatan yang lebih mudah ialah menggunakan modul jejak balik, yang mempunyai banyak fungsi tambahan terbina dalam untuk mengekstrak maklumat pengecualian.
Kini kami telah memperkenalkan pengetahuan asas Cangkuk Pengecualian Seterusnya, kami boleh menyesuaikan cangkuk pengecualian dan menambah beberapa ciri praktikal.
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}")
Selain contoh yang diperkenalkan di atas, anda juga boleh mengeluarkan pembolehubah setempat bagi setiap bingkai atau cari pembolehubah dirujuk dalam baris di mana pengecualian berlaku. Cangkuk Pengecualian ini sudah sangat matang Berbanding dengan cangkuk Pengecualian tersuai, saya cadangkan anda membaca kod sumber pembangun lain dan mempelajari idea reka bentuk mereka.
Memang menarik untuk menyesuaikan Cangkuk Pengecualian, tetapi banyak perpustakaan pihak ketiga telah melaksanakan fungsi ini. Daripada mencipta semula roda, lihat alat hebat yang lain.
# 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()
Dalam selain import langsung, kod di atas juga menunjukkan beberapa konfigurasi pilihan perpustakaan. Lebih banyak konfigurasi boleh dilihat di sini: Konfigurasi [3]
# 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可能会丢失某些关键信息,例如:本文中的某些例子中,输出中缺少文件路径,在远程调试代码这无疑很不方便,因此,需要谨慎使用。
Atas ialah kandungan terperinci Tingkatkan pengetahuan anda! Maklumat pengecualian Python juga boleh dipaparkan seperti ini. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!