1. 程式人生 > >pycallgraph 追蹤Python函數內部調用

pycallgraph 追蹤Python函數內部調用

content 追蹤 -c 分享 適用於 image urllib2 依賴 param

    • 安裝
      • 安裝pycallgraph
      • 安裝依賴
    • 使用
      • 待測腳本
      • 追蹤腳本
      • 追蹤結果
    • 高級篇
      • 隱藏私密函數
      • 控制最大追蹤深度
    • 總結

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

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


安裝

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

技術分享圖片

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

安裝pycallgraph

pip install pycallgraph
  • 1

安裝依賴

graphviz2.38 畫圖庫下載鏈接為:

http://www.softpedia.com/dyn-postdownload.php/adf89304319dca207ef04cd94d39e586/57ff4c63/1e6eb/4/1?tsf=0

下載完之後,為了不出現之前的那個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!"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

然後我們就可以使用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‘)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

追蹤結果

運行完腳本後,此文件夾中的細節如下:

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

沒有子文件夾
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在成功的下載了一張百度的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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

技術分享圖片

控制最大追蹤深度

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

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

技術分享圖片

總結

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

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!https://blog.csdn.net/jiangjunshow

pycallgraph 追蹤Python函數內部調用