PySnooper与Rich库学习

最近看到两个Python的包,1)pysnooper(偷窥狂)2)Rich

Pysnooper是一个用来代替print在代码调试的是否监看程序运行情况的库

Rich是一个美化输出结果的库,主要想用这个美化一下输出的结果

Pysnooper学习

目前有14K的star,而且还有个TorchSnooper的专门用来调试pytorch的库,先学习一下Pysnooper的基本使用方法

函数snooper

Github上的示例

在要分析的函数加入@pysnooper.snoop()装饰器语法糖,然后在被调用时会自动输出全部中间结果

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:... /my_code/foo.py
Starting var:.. number = 6
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         7         while number:
15:29:11.327032 line         8             number, remainder = divmod(number, 2)
Modified var:.. number = 1
Modified var:.. remainder = 1
15:29:11.327032 line         9             bits.insert(0, remainder)
Modified var:.. bits = [1, 0]
15:29:11.327032 line         7         while number:
15:29:11.327032 line         8             number, remainder = divmod(number, 2)
Modified var:.. number = 0
15:29:11.327032 line         9             bits.insert(0, remainder)
Modified var:.. bits = [1, 1, 0]
15:29:11.327032 line         7         while number:
15:29:11.327032 line        10         return bits
15:29:11.327032 return      10         return bits
Return value:.. [1, 1, 0]
Elapsed time: 00:00:00.000001

过程snooper

也可以不对函数而对一段代码进行snoop分析,使用with语句实现此功能

import pysnooper
import random

def foo():
    lst = []
    for i in range(10):
        lst.append(random.randrange(1, 1000))

    with pysnooper.snoop():
        lower = min(lst)
        upper = max(lst)
        mid = (lower + upper) / 2
        print(lower, mid, upper)

foo()

输出结果

New var:....... i = 9
New var:....... lst = [681, 267, 74, 832, 284, 678, ...]
09:37:35.881721 line        10         lower = min(lst)
New var:....... lower = 74
09:37:35.882137 line        11         upper = max(lst)
New var:....... upper = 832
09:37:35.882304 line        12         mid = (lower + upper) / 2
74 453.0 832
New var:....... mid = 453.0
09:37:35.882486 line        13         print(lower, mid, upper)
Elapsed time: 00:00:00.000344

pysnooper.snoop()参数分析

默认参数:输出文件位置,将输出结果存到log中而不是控制台

@pysnooper.snoop('/my/log/file.log')

watch:加入监看哪些非局部变量的值

@pysnooper.snoop(watch=('foo.bar', 'self.x["whatever"]'))

depth:函数监看深度

watch_explode

prefix:添加前缀

Remove all machine-related data (paths, timestamps, memory addresses) to compare with other traces easily:

@pysnooper.snoop(normalize=True)

On multi-threaded apps identify which thread are snooped in output:

@pysnooper.snoop(thread_info=True)

另外还可以定制输出(list、dict、numpy、tensor、。。。)