电竞比分网-中国电竞赛事及体育赛事平台

分享

如何動態(tài)調(diào)試Python的第三方庫

 imelee 2017-02-13

注意:本文方法僅限于調(diào)試安裝時附帶py源碼的庫,如sklearn。

引入

sklearn中的sklearn.feature_extraction.text.TfidfTransformer來獲取TF特征,但發(fā)現(xiàn)sklearn的計算結(jié)果與我手工計算結(jié)果不一樣。雖然能在github上找到sklearn源碼。但不能動態(tài)調(diào)試,就無法直觀的看到結(jié)果。

那么問題來了,我們怎么樣才能動態(tài)調(diào)試Python的第三方庫(比如sklearn)呢?怎么樣才能看到第三方庫中源碼動態(tài)運(yùn)行的中間結(jié)果?

假設(shè)我的代碼如下:

# 原始語料,3個文本
strs_train =[
'God is love',
'OpenGL on the GPU is fast',
'Doctor David is PHD']

from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
# 先提取 Bags of words特征
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(strs_train)
# 再基于Bags of words特征,變換為TF特征
tf_transformer = TfidfTransformer(use_idf=False).fit(X_train_counts)
X_train_tf = tf_transformer.transform(X_train_counts)
print(X_train_tf.todense())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

我怎么樣才能看到函數(shù)sklearn.feature_extraction.text.TfidfTransformer.transform()計算的中間結(jié)果呢?

Python調(diào)試基礎(chǔ)

Python自帶了一個用于調(diào)試代碼的模塊pdb。它支持?jǐn)帱c設(shè)置,單步調(diào)試,進(jìn)入函數(shù)調(diào)試,查看代碼片段,查看變量值,動態(tài)改變變量值。

下面兩行代碼就能給程序加斷點:

import pdb
pdb.set_trace()
  • 1
  • 2
  • 1
  • 2

加了斷點,運(yùn)行程序,當(dāng)程序停下,就可以用下面幾個命令,在SHELL中調(diào)試代碼。

命令 含義
c 繼續(xù)執(zhí)行代碼
n 下一步
r 執(zhí)行代碼,從當(dāng)前函數(shù)返回
s 進(jìn)入函數(shù)
b 下斷點

調(diào)試Python第三方庫

我們用pdb,就可以在第三方庫中下斷點,并進(jìn)行調(diào)試。這里以調(diào)試sklearn中的sklearn.feature_extraction.text.TfidfTransformer為例,給出如下步驟。

  • (1)找到第三方庫所在的位置

先利用如下Python代碼找到sklearn源碼位置。我的位置在C:\\Users\\biny\\Anaconda3\\lib\\site-packages\\sklearn。

import sklearn, os
path = os.path.dirname(sklearn.__file__)
  • 1
  • 2
  • 1
  • 2
  • (2)刪掉Python預(yù)編譯的字節(jié)碼

Python程序在運(yùn)行時,為了提高運(yùn)行速度,Python解釋器先將.py代碼編譯為byte code字節(jié)碼),再有Python虛擬機(jī)來執(zhí)行字節(jié)碼。

下次再運(yùn)行同一程序時,若.py代碼沒有改變,則省略將.py代碼編譯為字節(jié)碼的步驟,直接運(yùn)行上次已編譯好的字節(jié)碼。

這些字節(jié)碼,會被存于__pycache__文件夾下,和.pyc文件。按照原理,這個步驟是不需要做的,不過刪掉字節(jié)碼在運(yùn)行自己的程序,如果不會出現(xiàn)新的字節(jié)碼文件,說明你的第三方庫位置找錯了。這樣能方便我們發(fā)現(xiàn)錯誤。

  • (3)在第三方庫源碼中加斷點

根據(jù)第三方庫的位置,找到sklearn.feature_extraction.text.TfidfTransformer.transform()函數(shù)所在.py文件。并用pdb在函數(shù)開頭加上斷點(如下)。

def transform(self, X, copy=True):
    import pdb
    pdb.set_trace()

    if hasattr(X, 'dtype') and np.issubdtype(X.dtype, np.float):
        # preserve float family dtype
        X = sp.csr_matrix(X, copy=copy)
    else:
        # convert counts or binary occurrences to floats
        X = sp.csr_matrix(X, dtype=np.float64, copy=copy)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • (4)運(yùn)行自己的程序

運(yùn)行我的代碼,停在第三方庫中,就可以用pdb命令調(diào)試第三方代碼了。

  • 此時代碼已經(jīng)運(yùn)行并進(jìn)入第三方庫中,停止在斷點處:
    C:\mine\tmp\debug_py_3rd_lib>python main.py

    c:\users\biny\anaconda3\lib\site-packages\sklearn\feature_extraction\text.py(1018)transform()
    -> if hasattr(X, ‘dtype’) and np.issubdtype(X.dtype, np.float):
    (Pdb)

  • 用n命令(next),讓代碼單步運(yùn)行到關(guān)鍵點:

    c:\users\biny\anaconda3\lib\site-packages\sklearn\feature_extraction\text.py(1042)transform()
    -> if self.norm:
    (Pdb) n

  • 直接輸入要查看的中間變量(X.data),停下的這行代碼是即將執(zhí)行的,我們可以看到執(zhí)行前的變量值:

    c:\users\biny\anaconda3\lib\site-packages\sklearn\feature_extraction\text.py(1043)transform()
    -> X = normalize(X, norm=self.norm, copy=False)
    (Pdb) X.data
    array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

  • 繼續(xù)執(zhí)行代碼(n命令),然后可以看到中間變量值被改變。也能看到這個改變是因為做了normalize。
    (Pdb) n

    c:\users\biny\anaconda3\lib\site-packages\sklearn\feature_extraction\text.py(1045)transform()
    -> return X
    (Pdb) X.data
    array([ 0.57735027, 0.57735027, 0.57735027, 0.40824829, 0.40824829,
    0.40824829, 0.40824829, 0.40824829, 0.40824829, 0.5 ,
    0.5 , 0.5 , 0.5 ])

記住調(diào)試結(jié)束后,一定要在第三方源碼中刪掉pdb斷點那兩行代碼!

參考

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多