DeBug Python代码全靠print函数?

发表于:2019-4-25 10:34

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:佚名    来源:机器之心

#
Python
  
   DeBug Python代码全靠print函数?换用这个一天2K+Star的工具吧  
   print 函数已老,DeBug 该靠 PySnooper 了~
  小伙伴们,你们都怎样 DeBug Python 代码?是不是常用 print 大法?在本文介绍的这个项目中,deBug Python 代码再也不需要 print 了。只要给有疑问的代码加上装饰器,各种信息一目了然,找出错误也就非常简单了。
  这个名为 PySnooper 的项目是刚开源的,仅仅一天就获得了 2K+ 的 Star 量,当然这「一天」还没结束,这个收藏量也会继续刷新。
  项目地址:https://github.com/cool-RR/pysnooper
  Python 怎样 DeBug?
  如果写着写着模型,发现模型不 work 了,那么你该怎样找出 Python 的错误语句?这种错误一般与语法无关,而是某个变量的运算发生了错误。接下来我们就要慢慢找哪个地方有问题了,这里最常见、最直观的方法就是 print 大法。把我们怀疑的变量打印出来,总会找到异常的地方。
  如果代码中嵌入了单元测试,例如 assert 语句,那么还能缩小一些怀疑范围。但通常我们都要多次尝试,打印多个变量才能找到错误的地方。在 PyTorch 或 Keras 这样的动态计算图还好,打印出来的直接是一个值,像 TensorFlow 这样的静态计算图,打印出来是张量信息而不是值,这就很尴尬了。
  实际上不止是机器学习,在我们写 Python 的时候,总是想搞清楚为什么写的代码在运行时有点不大对。很多读者乐于使用断点等成熟的 DeBug 工具,也有的直接使用 print 大法找错误的地方。但现在我们不需要担心了,本文将介绍一个新的开源工具,它信心满满地呼吁到:「不要再使用 print 函数来 DeBug 啦~」
  极简DeBug工具PySnooper
  一般情况下,想要知道哪一行代码在运行、哪一行不运行、本地变量的值是多少时,大部分人会使用 print 函数,在关键部分打印某个或某组变量的值、形状、类型等信息。
  而 PySnooper 让你能快速地获得这些信息,且相比之下它不需要细致地写 print 函数,只需要向感兴趣的函数增加一个装饰器就行了。我们会得到该函数的详细 log,包含哪行代码能运行、什么时候运行以及本地变量变化的确切时间。
  相比于其他代码智能工具,PySnooper 为何如此优秀?因为不需要任何设置,你就可以在劣等、不规则的企业代码库上使用 PySnooper。只需要加个装饰器,并为日志输出地址指定路径就行了。
  这样说可能不太直观,下面我们可以具体看个案例,PySnooper 的优秀就能一目了然。
  PySnooper 案例
  下面项目作者写了一个函数以将数值转换为二进制码,该函数返回的是一个二进制列表。下面我们将装饰器 @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)
  该函数返回的日志如下,我们可以看到在调用 number_to_bits 函数时,赋予参数 number 的初始值为 6。然后,PySnooper 就还是对着源代码一行行分析了。
  如上分析所示,函数每创建一个新变量,那么这个变量的值、这个变量的变化都会展示出来。而且 PySnooper 还将循环展开,因此变化的细节更加明确。最终 6 的二进制版本应该是 [1, 1, 0],它的变化过程也展示在 bits 变量中。
  现在通过这些详细信息,PySnooper 再也不用担心我们用 print 函数强行 deBug 了。
  PySnooper 详细特征
  如果标准错误输出难以获得,或者太长了,那么可以将输出定位到本地文件:
 @pysnooper.snoop('/my/log/file.log')
  查看一些非本地变量的值:
 @pysnooper.snoop(variables=('foo.bar', 'self.whatever'))
  展示我们函数中调用函数的 snoop 行:
 @pysnooper.snoop(depth=2)
  将所有 snoop 行以某个前缀开始,更容易定位和找到:
 @pysnooper.snoop(prefix='ZZZ ')
  演示 PySnooper
  下面我们最开始尝试使用 PySnooper 获取 TensorFlow 的信息,如果它能获取各种张量信息,那可就太强大了。
  首先使用 pip 安装包:
 pip install pysnooper
  果然,TensorFlow 这种静态图并不能很好地获取信息,读者也可尝试一下。后面我们试了试 NumPy,希望能获取整个计算流的信息。如下代码所示,我们创建了两个数组变量,并且 2×2 的矩阵会连乘多次,如果能追踪到这种连乘,那就比较好处理错误。
   import pysnooper
  import numpy as np
  @pysnooper.snoop()
  def multi_matmul(times):
  x = np.random.rand(2, 2)
  w = np.random.rand(2, 2)
  for i in range(times):
  x = np.matmul(x, w)
  return x
  multi_matmul(3)
  对于 NumPy,该工具确实能追踪所有可疑变量的变化过程。当然在实际运算中,矩阵乘法的维度会非常大,我们可以直接追踪形状(Shape),而不是具体的值。

     上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号