1. 程式人生 > >python--debug神器pysnooper

python--debug神器pysnooper

使用它你可以獲得什麼優勢:

(1)無需用print就可以獲得變數的值;

(2)以日誌地形式進行儲存,方便隨時檢視;

(3)可以根據需要,設定呼叫函式的深度;

(4)多個函式的日誌,可以設定字首進行標識;

1.安裝

pip install pysnooper

2.官方程式碼

import pysnooper
@pysnooper.snoop()
def number_to_bits(number):
    if number:
        bits = []
        while number:
            number, remainder = divmod(number, 2)
            bits.insert(0, remainder)
        return bits
    else:
        return [0]
number_to_bits(6)

我們可以看到程式執行到哪一步, 以及到那一步時相關變數的值。

若果你不想追蹤整個函式,你可以像這樣使用:

def foo():
    lst = []
    for i in range(10):
        lst.append(random.randrange(1, 1000))

    with pysnooper.snoop():
        lower = min(lst)
        upper = max(lst)
        mid = (lower + upper) / 2
        print(lower, mid, upper)
foo()

檢視一下其原始碼,發現其具有一下引數:

  • output引數。該引數指定函式執行過程中產生的中間結果的儲存位置,若該值為空,則將中間結果輸出到控制檯。
  • watch引數。該引數是vector型別, 因為在預設情況下,裝飾器只跟蹤區域性變數,要跟蹤非區域性變數,則可以通過該欄位來指定。預設值為空vector。
  • watch_explode引數:展開顯示物件的屬性或者列表/字典的值。
  • depth引數。該引數表示需要追蹤的函式呼叫的深度。在很多時候,我們在函式中會呼叫其他函式,通過該引數就可以指定跟蹤呼叫函式的深度。預設值為1。
  • prefix引數。該引數用於指定該函式介面的中間結果字首。當多個函式都使用的該裝飾器後,會將這些函式呼叫的中間結果儲存到一個檔案中,此時就可以通過字首過濾不同函式呼叫的中間結果。預設值為空字串。
  • thread_info引數,在多執行緒應用程式上,確定在輸出中監聽到哪個執行緒。
  • custom_repr引數,PySnooper支援裝飾生成器。它將自動將修飾符應用於所有方法。(不包括屬性和其他特殊情況。)
  • max_variable_length引數,預設情況下,變數和異常被截斷為100個字元。
  • nomarlize引數,刪除所有與機器相關的資料(路徑,時間戳,記憶體地址),以便與其他跟蹤輕鬆進行比較。
其實,比較重要的就是前面幾個引數。對於一般情況下也就夠用了,接下來用幾個小例子來看下效果。 例子1:
@pysnooper.snoop()
def test(n):
    if n==1:
        return 1
    if n==2:
        return 2
    return test(n-1)+test(n-2)

test(4)

例子2:

@pysnooper.snoop("quick_sort.txt")
def quick_sort(a):
    if len(a)<=1:
        return a
    tmp=a[0]
    left = [i for i in a[1:] if i<=tmp]
    right = [i for i in a[1:] if i > tmp]
    return quick_sort(left)+[tmp]+quick_sort(right)

quick_sort([3,5,9,4,7,2,8])

輸出比較長,就不顯示全部的結果了。 

例子3:

class Foo(object):
    def __init__(self):
        self.num1 = 0
        self.num2 = 0
        self.sum_value = 0

    def add(self, num1, num2):
        return num1 + num2
    @pysnooper.snoop(output="debug.log", watch=("self.num1", "self.num2", "self.sum_value"))
    def multiplication(self, num1, num2):
        self.num1 = num1
        self.num2 = num2
        sum_value = 0
        for i in range(0, num1):
            sum_value = self.add(sum_value, num2)
        self.sum_value = sum_value
        return sum_value

foo = Foo()
foo.multiplication(3, 4)

 注意字首名字變了,以及全域性變數的值。