导航菜单
首页 » 炒股策略工厂 » 正文

吉他社-Python里三个最高逼格的调试神器

原创: 大刘 菜鸟学Python


调试是开发进程中不可避免的一个环节,在Python中咱们运用print、logging、assert等方法进行调试既简略又有用,但毕竟有其局限性。今日这篇文章为咱们带来三个东西,其间有Python的内置模块也有第三方库,它们供给了调试代码所需的大部分常用功用,将极大的提高咱们的开发和bug扫除功率。


1.PDB

pdb是Python中的一个内置模块,启用pdb后能够对代码进行断点设置和盯梢调试。为了演示便利,咱们预备一个样例程序pdb_test.py:

def countnumber(number):
for i in range(number):
print(i)
if __name__ == '__main__':
countnumber(10)


之后在终端中输入py吉他社-Python里三个最高逼格的调试神器thon -m pdb pdb_test.py指令,进入pdb的调试方式:


这时咱们就能够经过各种指令操控代码履行或许检查当时变量,例如l能够检查一切代码,n是履行下一步代码,p能够检查当时变量等等,需求留意的是指令n只会履行主程序中的代码,假如想要单步履行子函数中的代码,需求运用s指令,调试作用如下:


能够看到,经过s指令(假如只想在主函数中单步履行能够运用n)和p指令,咱们操控程序单步运转并实时检查了相关变量。可是单步履行毕竟是一种功率十分低下的调试方法,特别当代码量比较大的时分更是噩梦,这时就需求用到pdb的set_trace()方法,咱们对样例程序pdb_test.py做一点修正:

import pdb
def countnumber(number):
for i in range(number):
print(i)
pdb.set_trace()
if __name__ == '__main__':
countnumber(10)


pdb.set_trace()的作用就是在代码中设置断点,在pdb调试方式下,运用c指令就会直接跳转到下一个断点方位,假如之后没有其他断点就会履行完悉数代码,调试作用如下:


除了上面说到的几个指令以外,pdb还有其他一些比较常用的指令(见下表),归纳运用根本能够满意日常的调试需求。


2.Better-exceptions

better-exceptions是一个Python第三方库,作者对他的界说是“使反常信息愈加漂亮和翔实”。在正式运用之前先说下这个库的装置:

  • 第一步,运用pip install better_exceptions装置better-exceptions库;
  • 第二步,运用export BETTER_EXCEPTIONS=1(Linux / OSX)或setx BETTER_EXCEPTIONS 1(Windows)设置环境变量。

现在就能够正常运用better-exceptions进行调试了,为了演示作用愈加显着,咱们对上文中的代码稍作修正作为本次的样例程序better_test.py:

def divisionnumber(number, div):
for i in range(div):
print(number / i)
if __name__ == '__main__':
divisionnumber(10, 10)


很显着,上面这段代码在履行进程中会因为分母为0而抛出反常,现在咱们履行python better_test.py,看看启用了better-exceptions后的反常信息是什么姿态的:

从上面这幅图能够看出better-exceptions对反常信息的修正首要体现在两个方面:

  • 一是对发生反常的代码进行了色彩标示;
  • 二是对发生反常的代码中的相关变量值进行了输出(包含函数等目标);

这样一来,许多时分咱们只需求根据better-exceptions输出的辅佐信息就能判别发生反常的方位和原因,而不用像曾经相同再次检查源代码并调查运转成果,正如作者所说:Pretty and more helpful。

可是,过多的信息输出也会有问题,那就是当代码层级结构比较复杂的时分,better-exceptions输出的辅佐信息或许会十分之多,就比方上面的divisionnumber函数,他地点的地址信息大都时分咱们并不关怀,为了屏蔽这些“废物”信息,咱们能够在代码中加一行:

better_exceptions.MAX_LENGTH = XXX


XXX是答应显现的最大字符长度,比方这儿设置为10,再来运转better_test.py这个程序就会是下面的成果:


能够看到,对函数divisionnumber的注释只显现了最开端的"

除了上面说到的功用之外,better-exceptions还能够和logging还有django无缝接入,这使得它的运用愈加灵敏,关于这方面内容咱们能够检查项目文档。

还有一点需求提示咱们,假如你是在windows下运用,或许会出现下图中的乱码问题,这是因为better-exceptions的内设编码格局所导致的。


处理的方法是在装置后,对better_exceptions目录下的encoding.py文件第10行代码进行如下修正:

# 原代码:
ENCODING = locale.getpreferredencoding()
# 修正为:
ENCODING = 'utf-8'


3.PySnooper

PySnooper也是一个Python的第三方库,他的特点是能够精准的显现每条代码的履行次序、履行时刻以及随之带来的部分变量的改动等等。值得一提的是,作为一个发布不满半年的库,PySnooper在github上现已达到了1.2W星,其受欢迎程度可见一斑。

PySnooper的运用能够说是十分的便利,直接在代码中以装修器的方式调用就能够了。当然在引证前你得运用pip install pysnooper或许conda install -c conda-forge pysno吉他社-Python里三个最高逼格的调试神器oper装置这个库。咱们仍是举一个例子来进行演示,样例代码如下:


import pysnooper
import random
@pysnooper.snoop()
def foo():
lst = []
for i in range(10):
lst.append(random.randrange(1, 1000))
lower = min(lst)
upper = max(lst)
mid = (lower + upper) / 2
print(lower, mid, upper)
foo()


在上面这段代码中,咱们先是生成10个1到1000之间的随机数,然后核算他们之中的最大最小值和中位数,仅有的不同在于第三行多了一条句子@pysnooper.snoop(),咱们运转以下代码,发现除了正常的print成果之外,多了许多内容(内容太多,下面只显现一部分):

19:51:57.704857 call 16 def foo():
19:51:57.705860 line 17 lst = []
New var:....... lst = []
19:51:57.705860 line 18 for i in range(10):
New var:....... i = 0
19:51:57.705860 line 19 lst.append(random.randrange(1, 1000))
Modified var:.. lst = [758]
19:51:57.705860 line 18 for i in range(10):
Modified var:.. i = 1
....................
19:51:57.吉他社-Python里三个最高逼格的调试神器706818 line 22 upper = max(lst)
New var:....... upper = 927
19:51:57.706818 line 23 mid = (lower + upper) / 2
New var:....... mid = 552.0
19:51:57.706818 line 24 print(lower, mid, upper)
19:51:57.706818 return 24 print(lower, mid, upper)
Return value:.. None


这都是PySnooper盯梢监控的成果,吉他社-Python里三个最高逼格的调试神器正如上面所说,他精确记载的每条代码的运转时刻、次序以及相关的变量值

作为一个星标1.2W+的项目,PySnooper的功用必定不会这么简略,@pysnooper.snoop()中是能够接纳参数的,比方咱们觉得输出内容太多,能够考虑把信息记载到log日志中,这个功用只需求加一个log文件定位参数就能搞定:

@pysnooper.snoop('file.log')


@pysnooper.snoop()支撑的参数还有许多,别离对应了不同的功用,例恐龙图片大全如监控自界说表达式、监控底层函数、支撑多线程等等,详见项目文档。

此外,pysnooper还支撑部分监控,一般来说咱们写的代码都比较长,而需求监控的仅仅其间的一小部分,这时分就能够把需求监控的代码放到一个block里。咱们修正下方才的代码,只对核算最大最小值和中位数的部分进行监控,修正后的代码如下:

import pysnooper
import random
def foo():
lst = []
for i in range(10):
lst.append(random.randrange(1, 1000))
with p吉他社-Python里三个最高逼格的调试神器ysnooper.snoop():
lower = min(lst)
upper = max(lst)
mid = (lower + upper) / 2
print(lower, mid, upper)
foo()


运转之后发现监控信息精简了许多:

New var:....... lst = [562, 341, 552, 353, 628, 302, 430, 188, 955, 108]
Ne吉他社-Python里三个最高逼格的调试神器w var:....... i = 9
20:02:47.359272 line 21 lower = min(lst)
New var:....... lower = 108
20:02:47.359272 line 22 upper = max(lst)
New var:....... upper = 955
20:02:47.360269 line 23 mid = (lower + upper) / 2


运用with pysnooper.snoop()方式仍然保留了对各种参数的支撑,个人认为这种方式愈加契合实践需求。


小结:

今日介绍了三个不凭借IDE就能便利运用的调试东西,三个东西的调试思路和适用场景也各不相同,咱们能够根据需求灵敏选用。不过话说回来,我个人最喜爱的仍是PySnooper,你最喜爱哪一款呢?

最终,我自己是一名从事了多年开发的Python老程序员,辞去职务现在在做自己的Python私家定制课程,今年年初我花了一个月整理了一份最适合2019年学习的Python学习干货,能够送给每一位喜爱Python的小伙伴,想要获取的能够重视我的头条号并在后台私信我:Python,即可免费获取。

二维码