<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在日常開發中,我們的大部分時間都會花在閱讀traceback模組資訊以及偵錯程式碼上。本文我們將改進traceback模組,讓其中的提示資訊更加簡潔準確。
基於這一目的,我們將會自定義Exception Hooks(例外處理勾點),用來去除traceback中的冗餘資訊,只留下解決報錯所需的內容。此外,我還會介紹一些好用的第三方庫,你可以直接使用其中的Exception Hooks,來簡化traceback模組。
假如程式的異常資訊沒有被try/catch捕獲到,python直譯器就會呼叫sys.excepthook()函數,它會接收3個引數,分別是:type, value, traceback。這個函數也被稱為Exception Hook,會輸出程式的異常資訊。
我們來看看下面這個例子:
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
在這個例子中,我們可以從traceback (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
上述例子提供了一部分異常資訊,但要想獲取偵錯程式碼所需的全部資訊,並知道異常出現的時間及位置,我們還需要深入研究下traceback物件:
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'}
由上面的例子可以看出,traceback物件(tb)本質上是一個連結串列 - 儲存著所有出現的exceptions。因此可以使用tb_next對tb進行遍歷,並列印每一個異常的資訊。在此基礎上,還可以使用tb_frame.f_locals屬性將變數輸出到console中,這有助於偵錯程式碼。
使用traceback物件輸出異常資訊是可行的,但是比較麻煩,此外輸出的資訊可讀性較差。更方便的做法是使用traceback模組,該模組內建了許多提取異常資訊的輔助函數。
目前我們已經介紹了Exception Hooks的基礎知識,接下來我們可以自定義一個exception hooks,並加入一些實用的特性。
我們還可以讓異常資訊自動存入檔案中,在之後偵錯程式碼的時候檢視:
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中,如果你想改變儲存位置,可以這樣做:
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}")
除了上面介紹的例子,你還可以輸出每一幀的區域性變數,或者找到出現異常的行中所參照的變數。這些Exception Hooks已經很成熟了,相比於自定義Exception hooks,我建議你閱讀下其他開發者的原始碼,學習下他們的設計思路。
自定義一個Exception Hook很有趣,但許多第三方庫已經實現這一功能了。與其自己造輪子,不如看看其他優秀的工具。
首先,我個人最喜歡的是Rich,可以直接用pip進行安裝,隨後匯入使用。如果你只想在一個例子中使用,可以這樣做:python -m rich.traceback
# 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
better_exceptions也很受歡迎,我們需要先設定環境變數BETTER_EXCEPTIONS=1,再用pip安裝。此外,如果你的TERM變數不是xterm,還要把SUPPORTS_COLOR設定為True。
# 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
使用最方便的庫是pretty_errors,只需匯入即可:
# 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()
除了直接匯入外,上面的程式碼還顯示了該庫的一些可選設定。更多的設定可以檢視這裡:設定[3]
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()
stackprinter庫
# https://github.com/cknd/stackprinter # pip install stackprinter import stackprinter stackprinter.set_excepthook(style='darkbg2') do_stuff()
本文我們學習瞭如何自定義Exception Hooks,但我更推薦使用第三方庫。你可以在本文介紹的第三方庫中任選一個喜歡的,用到專案中。需要注意的是使用自定義Exception Hooks可能會丟失某些關鍵資訊,例如:本文中的某些例子中,輸出中缺少檔案路徑,在遠端偵錯程式碼這無疑很不方便,因此,需要謹慎使用。
到此這篇關於Python異常資訊的不同展現方法總結的文章就介紹到這了,更多相關Python異常資訊內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45