PySnooper:加个装饰器,告别 print 调试
PySnooper:加个装饰器,告别 print 调试
PySnooper 是一个 Python 调试工具,获得了 16,589 个 Star。它的核心思路很简单:在函数上加一个装饰器,就能自动输出该函数的执行过程、变量变化和耗时信息。

调试 Python 代码时,大多数人会在代码中插入 print 语句。这要求你手动决定输出哪些变量、在哪些行插入,还要时刻记得删除这些临时代码。如果逻辑比较复杂,print 语句会迅速膨胀,输出的信息也不容易阅读。
PySnooper 提供了一种替代方案。你只需要在目标函数上加一行 @pysnooper.snoop(),运行程序后 stderr 就会输出一份执行日志。这份日志记录了每一行代码的执行时间、变量何时被创建、值如何变化、函数何时返回。

下面是一个例子。我们定义一个将数字转成二进制位列表的函数:
import pysnooper
@pysnooper.snoop()
def number_to_bits(number):
if number:
bits = []
while number:
number, remainder = divmod(number, 2)
bits.insert(0, remainder)
return bits
else:
return [0]
number_to_bits(6)
运行后,输出内容如下:
Source path:... /path/to/foo.py
15:29:11.327032 call 4 def number_to_bits(number):
15:29:11.327032 line 5 if number:
15:29:11.327032 line 6 bits = []
New var:....... bits = []
15:29:11.327032 line 7 while number:
15:29:11.327032 line 8 number, remainder = divmod(number, 2)
New var:....... remainder = 0
Modified var:.. number = 3
15:29:11.327032 line 9 bits.insert(0, remainder)
Modified var:.. bits = [0]
...
15:29:11.327032 line 10 return bits
Return value:.. [1, 1, 0]
Elapsed time: 00:00:00.000067
每一条记录都包含时间戳、行号、代码内容,以及变量的创建和修改信息。返回时还会输出返回值和总耗时。
如果不需要追踪整个函数,只想观察某一段代码,可以使用 with 语句:
with pysnooper.snoop():
lower = min(lst)
upper = max(lst)
mid = (lower + upper) / 2
PySnooper 还支持一些配置项。将输出写入文件而不是 stderr:
@pysnooper.snoop('/my/log/file.log')
追踪指定的表达式(不限于局部变量):
@pysnooper.snoop(watch=('foo.bar', 'self.x["whatever"]'))
追踪函数内部调用的其他函数:
@pysnooper.snoop(depth=2)
安装方式:
pip install pysnooper
conda 用户也可以这样安装:
conda install -c conda-forge pysnooper
PySnooper 的优势在于不需要任何配置。不用设置断点、不用启动调试器,一行装饰器就能工作。在服务器上临时排查问题,或者不想打断开发节奏的时候,这个工具比较顺手。对于大型代码库,不用修改项目结构就能接入使用。
浙公网安备 33010602011771号