1. 程式人生 > >pycallgraph 追蹤Python函式內部呼叫

pycallgraph 追蹤Python函式內部呼叫

GitHub上好程式碼真的是太多了,名副其實的一個寶藏。但是最近自己也反思了一下,為什麼別人的程式碼看起來那麼的費勁。很多時候還不得要領,博主的笨方法就是先看下程式碼的結構,目錄。然後就從程式的入口出發了,一步步的往底層去追溯,但是因為忒懶,也沒有超大的臨時記憶空間,於是程式碼跟著跟著就跑偏了,這也是看別人程式碼的時候效率不高的主要原因。

幸運的是,發現了一款神器,pycallgraph,其作用就是追蹤函式的相互呼叫的情況,如此一來,對每個函式的的追蹤將一覽無餘。

安裝

安裝這個庫是比較簡單的,但是安裝好了是不能用的。

這裡寫連結內容

因為還需要一個圖形庫的依賴(graphviz), 這個依賴是著名的貝爾實驗室的一位大牛寫的一個命令列下的作圖工具庫。超讚。

安裝pycallgraph

pip install pycallgraph

安裝依賴

graphviz2.38 畫相簿下載連結為:

下載完之後,為了不出現之前的那個command命令實效。我們還得將graphviz的path新增到電腦的系統變數中。

具體做法:

系統屬性->高階設定->環境變數->path->記得環境變數之間用英文的;號分隔開

使用

配置好了上面的步驟之後,就可以正式的使用pycallgraph咯。為了方便演示,這裡寫了一段簡單的指令碼。

待測指令碼

# downloadmusic.py
# 之前適用於下載QQ音樂的,這裡的作用就是下載一張圖片
import urllib2 import threading def download(url, path): data = urllib2.urlopen(url).read() open(path, 'wb').write(data) print "success!"

然後我們就可以使用pycallgraph來完成簡單的追蹤過程了。

追蹤指令碼

# 追蹤程式碼
# coding: utf8
from pycallgraph import PyCallGraph
from pycallgraph import Config
from pycallgraph.output import
GraphvizOutput from downloadmusic import * graphviz = GraphvizOutput(output_file=r'./trace_detail.png') with PyCallGraph(output=graphviz): download('http://www.baidu.com/img/bd_logo1.png', r'./baidu.png')

追蹤結果

執行完指令碼後,此資料夾中的細節如下:

F:\temp\downloadmusic>tree /F
卷 娛樂 的資料夾 PATH 列表
卷序列號為 0000-4823
F:.
    baidu.png
    calldetails.py
    downloadmusic.py
    downloadmusic.pyc
    trace_detail.png

沒有子資料夾

在成功的下載了一張百度的logo照片之後,我們不難發現,多了一個叫trace_detail.png 的檔案。
如下:

追蹤情況

是不是感覺還不賴呢?函式之間的依賴關係,呼叫情況都可以得到很好的追溯。

高階篇

所謂高階,就是附加了點小情況而已。無非加個過濾條件,控制一下函式呼叫的追蹤深度。

隱藏私密函式

如題,隱藏那些不想看到的函式的名稱,這一點在某些情況下還是很好用的。

rom pycallgraph import PyCallGraph
from pycallgraph import Config
from pycallgraph import GlobbingFilter
from pycallgraph.output import GraphvizOutput

from banana import Banana


config = Config()
config.trace_filter = GlobbingFilter(exclude=[
    'pycallgraph.*',
    '*.secret_function',
])

graphviz = GraphvizOutput(output_file='filter_exclude.png')

with PyCallGraph(output=graphviz, config=config):
    banana = Banana()
    banana.eat()

隱藏函式

控制最大追蹤深度

這一點也很好理解了吧,待會看完圖就更加清晰了。

from pycallgraph import PyCallGraph
from pycallgraph import Config
from pycallgraph.output import GraphvizOutput

from banana import Banana


config = Config(max_depth=1)
graphviz = GraphvizOutput(output_file='filter_max_depth.png')

with PyCallGraph(output=graphviz, config=config):
    banana = Banana()
    banana.eat()

控制深度輸出

總結

這次的文章沒什麼技術含量,但是確實很實用的一篇介紹性的文章。下次讀程式碼遇到瓶頸的時候,不妨來嘗試一把這個工具。相信會讓你眼前一亮的。