GitHub上好代码真的是太多了,名副其实的一个宝藏。但是最近自己也反思了一下,为什么别人的代码看起来那么的费劲。很多时候还不得要领,博主的笨方法就是先看下代码的结构,目录。然后就从程序的入口出发了,一步步的往底层去追溯,但是因为忒懒,也没有超大的临时记忆空间,于是代码跟着跟着就跑偏了,这也是看别人代码的时候效率不高的主要原因。

幸运的是,发现了一款神器,pycallgraph,其作用就是追踪函数的相互调用的情况,如此一来,对每个函数的的追踪将一览无余。


安装

安装这个库是比较简单的,但是安装好了是不能用的。

因为还需要一个图形库的依赖(graphviz), 这个依赖是著名的贝尔实验室的一位大牛写的一个命令行下的作图工具库。超赞。

安装pycallgraph

pip install pycallgraph

安装依赖

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!"

然后我们就可以使用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()

总结

这次的文章没什么技术含量,但是确实很实用的一篇介绍性的文章。下次读代码遇到瓶颈的时候,不妨来尝试一把这个工具。相信会让你眼前一亮的。

pycallgraph 追踪Python函数内部调用的更多相关文章

  1. 你好,C++(27)在一个函数内部调用它自己本身 5.1.5 函数的递归调用

    5.1.5 函数的递归调用 在函数调用中,通常我们都是在一个函数中调用另外一个函数,以此来完成其中的某部分功能.例如,我们在main()主函数中调用PowerSum()函数来计算两个数的平方和,而在P ...

  2. python 函数的调用 和执行 小知识

    1.符号表 执行一个函数会引入一个用于函数的局部变量的新符号表. 更确切地说, 函数中的所有的赋值都是将值存储在局部符号表: 而变量引用首先查找局部符号表, 然后是上层函数的局部符号表, 然后是全局符 ...

  3. python函数及调用

    python的函数是一段重复多次可调用的代码,依据python的函数,我们可以利用函数式的编程,来减少代码的重复. 在本章节中,详细的介绍python的函数,以及python的函数式编程的与众不同,函 ...

  4. Python函数递归调用

    函数的递归调用: 是函数嵌套调用的一种特殊形式 具体是指: 在调用一个函数的过程中又直接或间接地调用到了本身 # 直接调用本身 def func(): print('我是func') func() f ...

  5. python类内部调用自己的成员函数必须加self

    class A: def a(self): print("hello world") def b(self): return self.a() 上面的self.a()中self是不 ...

  6. python函数之调用函数

    调用函数 python中内置了许多函数,我们可以直接调用,但需要注意的是参数的个数和类型一定要和函数一致,有时候不一致时,可以进行数据类型转换 1.abs()函数[求绝对值的函数,只接受一个参数] # ...

  7. python函数进阶(函数参数、返回值、递归函数)

    函数进阶 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形 ...

  8. python函数(二)

    python函数(二) 变量的作用域 1.局部变量与全局变量 在函数内创建的变量被称为局部变量,这类变量的生命周期与函数相同,当函数执行完毕时,变量也就随之消失. 此类变量只能在函数内部调用,函数外不 ...

  9. python函数进阶

    知识内容: 1.函数即变量 2.嵌套函数 3.lambda表达式与匿名函数 4.递归函数 5.函数式编程简介 6.高阶函数与闭包 一.函数即变量 1.变量的本质 声明一个变量,在python里本质上讲 ...

随机推荐

  1. 计算机网络-应用层之HTTP协议

    1.概念 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写:HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等). ...

  2. [LeetCode] Word Abbreviation 单词缩写

    Given an array of n distinct non-empty strings, you need to generate minimal possible abbreviations ...

  3. angularjs中使用 <input type="file">标签实现一次最多上传5张图片

    前期准备: 1.angular.js 2.bootstrap.css 具体如何实现呢?请看下面代码哈哈哈. 在angular项目中,如果要给<input type="file" ...

  4. Anaconda入门安装教程

    Anaconda 是什么? Anaconda 是一个可用于科学计算的 Python 发行版,支持 Linux.Mac.Windows系统,内置了常用的科学计算包.它解决了官方 Python 的两大痛点 ...

  5. Log4j1.2配置详解

    Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志的输出到控制台,或者文件等等. 同时,在各大框架中也主要是使用log4j来进行日志的输出. 下面是log4j1.x版本的详细 ...

  6. wows

    [问题描述]山山最近在玩一款游戏叫战舰世界(steam 游戏太少了),他被大舰巨炮的魅力折服,于是山山开了一局游戏,这次发现目标是一艘战列舰新墨西哥级,舰桥很高,原本应该打在目标身后的圆形水域内的炮弹 ...

  7. 3064: Tyvj 1518 CPU监控

    注意这题要维护历史最大加和历史最大覆盖 /************************************************************** Problem: 3064 Us ...

  8. hdu 5398 动态树LCT

    GCD Tree Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Su ...

  9. P1837 单人纸牌_NOI导刊2011提高(04)

    题目描述 单人纸牌游戏,共36张牌分成9叠,每叠4张牌面向上.每次,游戏者可以从某两个不同的牌堆最顶上取出两张牌面相同的牌(如黑桃10和梅花10)并且一起拿走.如果最后所有纸牌都被取走,则游戏者就赢了 ...

  10. 51Nod 1530 稳定方块

    瓦西亚和皮台亚摆放了m个方块.方块被编号为0到m-1(每个号码出现恰好一次).现在建立一个座标系OX表示地面,OY的方向是竖直向上的.每一方块的左下角有一个座标而且是整点座标. 摆放好的方块一定要是稳 ...