1. 程式人生 > 程式設計 >python 除錯冷知識(小結)

python 除錯冷知識(小結)

對於 python 程式碼的除錯我們通常都是使用 IDE 自帶的除錯功能。但是 IDE 提供的除錯功能存在侷限性,例如在測試伺服器上除錯程式碼,但是又不可能在測試伺服器上安裝 IDE 進行除錯。這時我們就可以利用下面所講解的三個工具進行除錯。

零、準備除錯程式碼

在講解三個除錯工具前,我們先編寫待除錯的程式碼。程式碼很簡單,就是計算兩個數的商。我們在編寫程式碼的時候故意留下了除數為 0 的 bug。

def division(start,end):
  for i in range(start,end,-1):
    num1 = i
    num2 = i - 1
    result = num1 / num2
    print(result)


if __name__ == '__main__':
  division(10,0)

一、PySnooper

PySnooper 是 Python 的第三方工具庫,它可以精確的顯示程式碼的執行時間、執行順序和程式碼中的區域性變數值的變化等。 PySnooper 使用方法很簡單,只需要將它作為裝飾器來使用即可。下面我們來看一下具體使用步驟:

安裝 PySnooper

1. 在控制檯輸入如下命令:

pip install pysnooper

等待兩秒鐘後 PySnooper 安裝完成。

2. 加入 PySnooper

首先需要引入 PySnooper

import pysnooper

接著在需要測試的函式上加上 pysnooper 裝飾器

@pysnooper.snoop()
def division(start,0)

除錯程式碼
在控制檯輸入命令:

python text.py

執行程式碼後,控制檯輸出如下內容

KmBTPI.png

KmB7Gt.png

上圖只截取了 PySnooper 輸出日誌的開頭內容和最後結尾的內容。從截圖中我們可以看到 PySnooper 輸出了每行程式碼的執行順序、執行時間和程式碼執行中變數值的變化,以及報錯資訊。在實際專案中 PySnooper 輸出的日誌內容會很多,在控制檯檢視會很不方便,這時我們可以將日誌輸出到本地檔案中,我們只需在 PySnooper 裝飾器中加入日誌儲存路徑即可:

@pysnooper.snoop('/app/project_log.log')

一些公司對日誌輸出會有要求,比如每行日誌要以某某字串開頭,這時只需在裝飾器中加入需要字元穿即可:

@pysnooper.snoop(prefix='MyCompanyName: ')

上述所講的都是 PySnooper 裝飾器的常用引數,例如監控自定義表示式、監控底層函式、多執行緒等 PySnooper 同樣支援,具體引數可以在官方專案文件中檢視。
前面我們所講的都是在函式上利用裝飾器來監控整個函式,但是在實際專案中往往一個函式內容會很多,如果監控整個函式會導致輸出的日誌過多,這時我們就可以利用 PySnooper 的區域性監控功能來監控函式中需要監控的程式碼片段。現在我們來修改一下程式碼,只監控輸出的值:

import pysnooper

def division(start,-1):
    with pysnooper.snoop():
      num1 = i
      num2 = i - 1
      result = num1 / num2
    print(result)


if __name__ == '__main__':
  division(10,0)

上述程式碼執行後我們就會發現輸出的內容少了很多。

二、Better-exceptions

Better-exceptions 同樣是 Python 的第三方工具庫,它出現的原因是其實很簡單就是“美化異常資訊”(是不是感覺作者很任性)。 Better-exceptions 主要使用了 Python 的 sys 模組的 excepthook 方法,這個方法在當系統丟擲異常時,直譯器就會呼叫它,同時傳遞三個引數:異常類、異常例項和 traceback 物件,這就說明我們可以重寫這個方法來捕獲系統異常。但是,因為我們可以重寫 excepthook 方法來捕獲系統異常,因此 Better-exceptions 對與 Web 框架來說是不起任何作用的,因為 Web 框架都已經處理了系統丟擲的異常,不會再以 hook 的方式觸發 Better-exceptions 。下面我們就來看一下該怎麼用。

安裝 Better-exceptions

首先在控制檯輸入如下命令:

pip install better-exceptions

等待兩秒鐘後 Better-exceptions 安裝完成。

接著我們在控制檯輸入如下程式碼,來設定環境變數:

setx BETTER_EXCEPTIONS 1

除錯程式碼
在控制檯輸入命令:

python text.py

程式碼執行後,控制檯輸出如下圖:

KuCr9S.png

從上面的圖我們可以看到,Better-exceptions 對異常程式碼進行了著色,並對產生異常的變數值進行了輸出。通過這兩項內容我們就可以很快捷的看到具體報錯位置和報錯原因。

這裡有需要注意的地方就是,在 Windows 系統下輸出的日誌會存在亂碼問題,這是因為 Better-exceptions 的編碼格式造成的。要解決這個問題我們只需要修改 better-exceptions 目錄下的 encoding.py 檔案,講檔案中的 ENCODING = locale.getpreferredencoding()修改為 ENCODING = 'utf-8'即可。

三、PDB

PDB 是 Python 內建的模組,我們可以利用 PDB 設定斷點和跟蹤除錯。 PDB 的使用不需要再安裝第三方外掛,只需要在命令列輸入如下命令:

python -m pdb Test.py

命令執行後將會進入 PDB 除錯模式。如果需要在程式碼中加入斷點,只需要在需要加入斷點的位置加入 pdb.set_trace()即可。當進入到 PDB 模式後,輸入 c 就可以從當前斷點直接跳轉到下一個斷點,如果後續沒有斷點,則會將剩餘程式碼執行完。當然,如果需要單步執行程式碼,在控制檯輸入 s 指令,但是有時主函式會呼叫大量的其他函式,這時在命令列輸入 n 就可以只在主函式中執行單步除錯。除了上述指令外,PDB 還有其他指令,如下表:

指令 說明
l 顯示所有程式碼
n 執行下一條程式碼
c 執行當前斷點後面的程式碼,知道程式碼執行完畢
b x 在程式碼的第X行設定斷點
clear 清除全部斷點
s 單步執行
s function_name 進入 function_name 函式內部執行
q 退出PDB
a 列印所有引數值
p 列印指定變數值
r 忽略剩餘斷點,將剩餘程式碼執行完畢

四、總結

我們講解了 PySnooper 、Better-exceptions 和 PDB 的用法,這三種方法一般都使用在伺服器上,這裡我推薦使用Better-exceptions,因為它對程式碼的侵入性很小,幾乎不需要改變程式碼。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。