print功能老了,DeBug要靠PySnooper了~小伙伴们,Python代码怎么调试呢?使用print方法是否很常见?在本文介绍的项目中,不再需要打印debugPython代码。只要给有问题的代码加上装饰器,各种信息一目了然,查找错误也非常简单。这个名为PySnooper的项目刚刚开源,仅一天就获得了2K+Stars。当然,这个“日子”还没有结束,本合集还会继续刷新。项目地址:https://github.com/cool-RR/pysnooperPython如何调试?如果你写了model,发现model不行,怎么找出Python报错语句呢?这种错误一般与语法无关,而是某个变量的操作错误。接下来,我们就慢慢找出哪里有问题。这里最常见和直观的方法是打印方法。把我们怀疑的变量打印出来,总能找到异常的地方。如果代码中嵌入了单元测试,比如assert语句,那么也可以减少一些怀疑。但是通常我们要尝试很多次,打印多个变量才能找到错误的地方。在像PyTorch或者Keras这样的动态计算图里,没关系,打印出来的直接是一个值。对于像TensorFlow这样的静态计算图,打印出张量信息而不是一个值是很尴尬的。事实上,这不仅仅是机器学习。我们在写Python的时候,总是想搞清楚为什么我们写的代码在运行时有点不对劲。很多读者乐于使用断点等成熟的Debug工具,也有的直接使用print方式查找错误。不过现在我们不用着急,本文将介绍一款新的开源工具,它自信地呼吁:“别再用打印功能来Debug了~”极简Debug工具PySnooper通常想知道的是哪一行当代码在运行,哪一行没有运行,局部变量的值是多少,大部分人会在关键部分使用print函数打印一个变量或一组变量的值、形状、类型等信息.PySnooper可以让你快速获取这些信息,相比之下它不需要详细编写打印函数,只需在感兴趣的函数中添加装饰器即可。我们得到了该函数的详细日志,包括运行了哪些代码行、运行时间以及局部变量更改的确切时间。与其他代码智能工具相比,为什么PySnooper如此出色?因为不需要设置,所以您可以在糟糕的、零星的企业代码库上使用PySnooper。只需添加一个装饰器并指定日志输出地址的路径即可。这么说可能不太直观,下面看一个具体的案例,PySnooper的优秀之处一目了然。PySnooper案例下面这个项目的作者写了一个函数将值转换为二进制代码,它返回一个二进制列表。接下来我们将装饰器@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)的function返回的日志如下,我们可以看到在调用number_to_bits函数时,参数number的初始值为6。然后,PySnooper依然是逐行分析源码。如上分析所示,函数每次新建一个变量,都会显示这个变量的值和这个变量的变化。而且PySnooper还将展开循环,因此更改的细节更加明确。6最终的二进制版本应该是[1,1,0],它的变化过程也体现在bits变量中。现在有了这些细节,PySnooper再也不用担心我们用打印函数强制调试了。PySnooper的详细功能如果标准错误输出不可用,或者太长,那么可以将输出定向到本地文件:@pysnooper.snoop('/my/log/file.log')查看一些非-的值局部变量:@pysnooper.snoop(variables=('foo.bar','self.whatever'))显示我们函数中调用函数的snoop行:@pysnooper.snoop(depth=2)更容易启动allsnooplineswithacertainprefix定位查找:@pysnooper.snoop(prefix='ZZZ')演示PySnooper接下来,我们首先尝试使用PySnooper获取TensorFlow信息。如果它能够获取各种张量信息,那就太强大了。首先使用pip安装包:pipinstallpysnooper果然像TensorFlow这样的静态图不能很好的获取信息,读者也可以试试。后来我们尝试了NumPy,希望能得到整个计算流程的信息。如下代码所示,我们创建了两个数组变量,2×2矩阵会进行多次相乘。如果我们可以跟踪这种乘法,那么处理错误会更好。importpysnooperimportnumpyasnp@pysnooper.snoop()defmulti_matmul(times):x=np.random.rand(2,2)w=np.random.rand(2,2)foriinrange(times):x=np.matmul(x,w)returnxmulti_matmul(3)对于NumPy来说,这个工具确实可以追踪到所有可疑变量的变化过程。当然在实际操作中,矩阵相乘的维度会很大,我们可以直接追踪形状(Shape)而不是具体的值。【本文为栏目组织《机器之心》微信公众号《机器之心(id:almosthuman2014)》原文翻译】点击此处查看作者更多好文
