Boxx • 一个快速调试 Python 代码的工具库

2018-06-22 01:28:56 +08:00
 diyer22

最近写了一个提高 Python 调试效率的工具包 boxx ,目前快完工了, 先分享出来,欢迎大家多提意见,也希望大家能喜欢这个工具。


先从打印开始介绍吧,打印变量是最简单、直接的 debug 方式, 那能不能更简单?

💡 Note: boxx.p 使用了 magic method, p/x 便会打印 x 并返回 x。这样便可以在任何地方打印,比如 例子中的 p/randint(0, 3) 就不需要新建变量便可直接打印

在函数内运行 p(),便会将函数或 module 内的所有变量名和值一同打印(相当于快捷打印 locals())

💡 Note: 在函数内 import boxx.pp() 有相同的效果

许多数情况下, 直接 print 无法获得调试的关键信息。比如变量是有很多属性的对象,numpy 等类型

这时 就必须对变量进行分析, 方式有:

  1. 在调试处加上 print(x.text, x.code, np.hasinf(x),.np.hasnan(x))
  2. 设置断点进行分析

方法 1 每改一次调试代码 都要运行整个代码, 不灵活,操作也繁琐。
方法 2 中进入和退出 Debug console 比较麻烦,Debug console 本身也不太好用(没有自动补全功能)
boxx.g 提供了一种新的方式,通过 g.name 可以将变量传到当前的 Python 交互终端

变量传到 Python 终端后,就能对变量进行全面分析了,比如 使用tree,what 来分析
💡 Note:

在函数内运行 g(),便会将函数 (或 module) 内的所有变量一同传到当前的 Python 交互终端

这样 任何错误都可以在终端中复现和分析了。当然, 注意不要覆盖重要的全局变量。
💡 Note: 在函数内 import boxx.gg() 有相同的效果

在实际开发调试中, 函数或 module 内可能含有非常多的变量 但我们只对几个变量感兴趣, with p, with g, with gg 可以使操作只作用于几个感兴趣的变量,只需把变量放入 with 结构中即可 :

💡 Note:

总结一下,boxx 的调试工具可以汇总为一个表

boxx 调试工具矩阵

💡 Note:

在学习新框架或适配大佬代码时,经常会使用 print(x), dir(x), help(x), type(x) 来了解某个变量的各方面的信息 (变量可能是 值 /function/class/module 等),于是我写了一个 boox.what(x) 来全面了解"what is x?":
💡 Note: what(x) 通过打印 x 自己及x文档, 父类继承关系, 内部结构所有属性 来全面了解 x. 是 help(x) 的补充.


说了这么多调试 再说一下性能调优

测试代码性能时,计时很常用, 我写了一个方便的计时工具boxx.timeit 将想要计时的代码块放入 with timeit(): 中就可以计时了:

此外 SnakeViz 是一个很棒的性能分析工具,SnakeViz 能够通过 cProfile 文件,来统计代码的函数调用情况,并可视化出代码的 火焰图。但是, 先生成 cProfile 文件,再运行 SnakeViz 的流程非常繁琐,我把这一套操作封装成了 boxx.performance 来简化流程:

💡 Note: performance 也支持字符串形式的 Python 代码.

在进行密集运算和处理时 得写多进程的 Python 代码 来榨干 CPU 的每一个线程获得加速。但我觉得 Python 多进程的几个范式都不够方便,我参照 map 的思想和用法把多进程操作封装成 boxx.mapmp 函数(意思是"Map for Mulit Processing"). mapmpmap 有一样的用法, 只需把 map 替换为 mapmp 即可获得多进程加速:

💡 Note:

对于网络爬虫等高 IO 操作,boxx 还有个多线程版本的 map -- mapmt (意思是 "Map for Mulit Threading")。mapmt 用法和 mapmp 一样, 但没有多进程的诸多限制。

在开发和适配代码时,会遇到一些复杂的 dict,list。boxx.tree 可以直观地展示复杂结构。


大致就介绍这些 boxx 的这些功能吧,欢迎大家多提意见!

项目信息

GitHub 主页:https://github.com/DIYer22/boxx(内含有更多说明)

教程:boxx 的教程是一个可执行的在线 Notebook。 也就是说,无需下载和运行任何代码,只需浏览器点击下面的链接,就可以在线执行 Notebook 教程中的代码块。
=> 可直接执行的在线教程

3366 次点击
所在节点    Python
13 条回复
laike9m
2018-06-22 02:57:30 +08:00
我很喜欢第一个功能加 p/ 在任意位置打印
what 那个功能我之前写过更好的,你直接用就行了: https://github.com/laike9m/pdir2
有几个功能是不是和 ipdb 耦合得太紧了?不用 ipdb 或者 notebook 能用么?像火焰图和 boxx.p
diyer22
2018-06-22 03:26:18 +08:00
@laike9m 前辈啊,之前和你的想法很接近,有想法后就直接动手实现了一个 `boxx.dira`( meaning `dira attribute`),后来又把能打印的信息都加上了 扩展成了 `boxx.what`。

整个项目都不需要 `ipdb` 或 notebook,可以在原始 Python 里直接使用,由于我主要做科学计算 更喜欢在 IPython 里面调试。

`boxx.p` 没有使用除了 `sys` 以外的包 火焰图用了标准库的 `cProfile`来产生调试文件 + `SnakeViz` 用浏览器可视化 `cProfile`文件
laike9m
2018-06-22 03:31:20 +08:00
“ boxx.g 提供了一种新的方式,通过 g.name 可以将变量传到当前的 Python 交互终端”
但用 pdb 调试的人(比如我),就不知道应该怎么用以及能不能用了
diyer22
2018-06-22 03:40:21 +08:00
@laike9m 我是觉得 pdb 的 debug console 的体验和 IPython 差太多,才写了这个功能。平时调试 `script.py` 都是在 IPython console 里面运行 `%run script.py` 来运行再调试。

P.S. 平时调试时,把整个 `local()` 复制出来的 `g()` 操作更常用
laike9m
2018-06-22 03:45:12 +08:00
有很多情况下程序是没法用 python xxx.py 来运行的(比如公司里的 binary ),而 pdb 是支持的,这个时候不知道还能不能用 IPython,当然我对 IPython 并不熟
diyer22
2018-06-22 03:49:02 +08:00
@laike9m python xxx.py 都无法运行 那还属于 Python 程序吗。。。。 好奇要如何运行。。。
laike9m
2018-06-22 03:53:43 +08:00
@diyer22 有很复杂的 build system,最后生成一个自带 interpreter 的 binary,不会这样裸着运行 Python 文件的
laike9m
2018-06-22 03:58:18 +08:00
diyer22
2018-06-22 04:09:42 +08:00
@laike9m 高端,涨姿势了。如果调试环境没有 Interactive console 能用的话,那应该用不上 boxx.g
mmqc
2018-06-22 08:48:12 +08:00
收藏,有空看
laike9m
2018-06-22 14:21:30 +08:00
@diyer22 我感觉如果没依赖 IPython 的东西,应该是能用的,毕竟 pdb 也是 interactive 调试。如果文档写清楚这点会更好。
diyer22
2018-06-22 14:24:46 +08:00
@laike9m 好的 我会考虑强调这一点的,谢谢建议😄
VVTA
2019-06-19 14:09:53 +08:00
进来学习下哈

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/464892

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX