一个可怜的Python调试器。

PySnooper的Python项目详细描述


pysnooper-不再使用print进行调试

Travis CI

pysnooper是一个穷人的调试器。

您正试图找出为什么您的python代码没有做您认为应该做的事情。您很想使用一个完整的带有断点和监视点的调试器,但现在您不必费心设置一个断点和监视点。

您想知道哪些行正在运行,哪些没有运行,以及本地变量的值是什么。

大多数人会在战略位置使用print行,其中一些显示变量的值。

pysnooper允许您执行相同的操作,但您只需在感兴趣的函数中添加一个装饰符行,而不是仔细地绘制正确的print行。您将获得函数的逐行播放日志,包括运行的行数、运行的时间以及更改局部变量的确切时间。

是什么使pysnooper在所有其他代码智能工具中脱颖而出?你可以在你那肮脏的、杂乱无章的企业代码库中使用它,而不必做任何设置。只需打开decorator,如下所示,并通过将其路径指定为第一个参数将输出重定向到专用日志文件。

示例

我们正在编写一个函数,通过返回一个位列表,将数字转换为二进制。让我们通过添加@pysnooper.snoop()装饰器来窥探它:

importpysnooper@pysnooper.snoop()defnumber_to_bits(number):ifnumber:bits=[]whilenumber:number,remainder=divmod(number,2)bits.insert(0,remainder)returnbitselse:return[0]number_to_bits(6)

stderr的输出是:

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]

或者如果不想跟踪整个函数,可以将相关部分包装在一个with块中:

importpysnooperimportrandomdeffoo():lst=[]foriinrange(10):lst.append(random.randrange(1,1000))withpysnooper.snoop():lower=min(lst)upper=max(lst)mid=(lower+upper)/2print(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)

功能

如果您不容易访问stderr,可以将输出重定向到文件:

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

您也可以传递流或可调用的,它们将被使用。

查看一些非局部变量表达式的值:

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

展开值以查看其所有属性或列表/词典项:

@pysnooper.snoop(watch_explode=('foo','self'))

这将输出如下行:

Modified var:.. foo[2] = 'whatever'
New var:....... self.baz = 8

(有关更多控制,请参见Advanced Usage

显示函数调用的函数的窥探行:

@pysnooper.snoop(depth=2)

用前缀开始所有窥探线,以便轻松地为它们添加grep:

@pysnooper.snoop(prefix='ZZZ ')

在多线程应用程序上,确定输出中窥探的线程:

@pysnooper.snoop(thread_info=True)

pysnooper支持装饰生成器。

您还可以自定义对象的repr:

deflarge(l):returnisinstance(l,list)andlen(l)>5defprint_list_size(l):return'list(size={})'.format(len(l))defprint_ndarray(a):return'ndarray(shape={}, dtype={})'.format(a.shape,a.dtype)@pysnooper.snoop(custom_repr=((large,print_list_size),(numpy.ndarray,print_ndarray)))defsum_to_x(x):l=list(range(x))a=numpy.zeros((10,10))returnsum(l)sum_to_x(10000)

您将获得列表的l = list(size=10000),以及ndarray的a = ndarray(shape=(10, 10), dtype=float64)custom_repr按顺序匹配,如果有一个条件匹配,则不会检查其他条件。

安装

您可以通过以下方式安装pysnooper

  • 管道:
$ pip install pysnooper
  • 带康达锻造通道的康达:
$ conda install -c conda-forge pysnooper

高级用法

watch_explode将根据其类自动猜测如何展开传递给它的表达式。您可以使用下列类中的一个进行更具体的说明:

importpysnooper@pysnooper.snoop(watch=(pysnooper.Attrs('x'),# attributespysnooper.Keys('y'),# mapping (e.g. dict) itemspysnooper.Indices('z'),# sequence (e.g. list/tuple) items))

使用exclude参数排除特定键/属性/索引,例如Attrs('x', exclude=('_foo', '_bar'))

Indices之后添加一个切片,以仅查看该切片中的值,例如Indices('z')[-3:]

$exportPYSNOOPER_DISABLED=1# This makes PySnooper not do any snooping

许可证

版权所有(c)2019 Ram Rachum和合作者,根据麻省理工学院许可证发布。

我提供Development services in Python and Djangogive Python workshops教人 python和相关主题。

媒体报道

Hacker News thread 以及/r/Python Reddit thread(2019年4月22日)

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
将PHP生成的公钥转换为Java公钥   java在服务中启动可取消的后台任务   java我能做这个通用的事情吗?   java Axis 1.4.1版在IBM上的部署为8.5版   java如何进行同步web服务调用   java从Spring控制器中的多个select获取值   java如何在JFrame中声明类(包含sapache Poi)的对象   jaxb反序列化XML以在Java中动态创建类   java如何为部署在Google云上的应用程序实现Google OAuth?   java我想了解libgdx的资产管理器   Java整数溢出   Windows任务管理器javaw。exe内存与Java任务控制   java如何让Android等待?