PySnooper:加个装饰器,告别 print 调试

PySnooper:加个装饰器,告别 print 调试

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

正文顶部截图

调试 Python 代码时,大多数人会在代码中插入 print 语句。这要求你手动决定输出哪些变量、在哪些行插入,还要时刻记得删除这些临时代码。如果逻辑比较复杂,print 语句会迅速膨胀,输出的信息也不容易阅读。

PySnooper 提供了一种替代方案。你只需要在目标函数上加一行 @pysnooper.snoop(),运行程序后 stderr 就会输出一份执行日志。这份日志记录了每一行代码的执行时间、变量何时被创建、值如何变化、函数何时返回。

README区域截图

下面是一个例子。我们定义一个将数字转成二进制位列表的函数:

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 的优势在于不需要任何配置。不用设置断点、不用启动调试器,一行装饰器就能工作。在服务器上临时排查问题,或者不想打断开发节奏的时候,这个工具比较顺手。对于大型代码库,不用修改项目结构就能接入使用。

posted @ 2026-06-20 16:28  techfusion55  阅读(7)  评论(0)    收藏  举报