python 调试模式_Python调试方法,python

廖雪峰官方网站

assert(断言,当程序出现期望之外的情况时,执行语句)

从功能上看跟if有些相同的地方,我们可以使用if进行预判,将可能产生的错误提前预知并处理。而assert是给定一个条件,条件之外的情况都是错误,它本身是一个用来判断错误的class,输出的是一个错误class的实例。

一般用在需要调试的代码的部分,方便记录变量信息,去定位出现问题的变 量。

如下:

import logging

def fun(e):

n=int(e)

assert n!=0,'n=%d' % n

return 10/n

fun(0)

运行结果为:

>>>

============================= RESTART: C:\日常学习代码.py ============================

Traceback (most recent call last):

File "C:\日常学习代码.py", line 6, in

fun(0)

File "C:\日常学习代码.py", line 4, in fun

assert n!=0,'n=%d' % n#当调试很多时,会出现大量的assert

AssertionError: n=0#提示的是AssertionError,并不是ZeroDivitionError

>>>

当代码中需要调试的部分很多,程序中就会出现很多的assert,在其中编译器时可以用-O参数来关闭assert,也就是通过CMD命令行启动时加上 -O。

Microsoft Windows [版本 10.0.18362.239]

(c) 2019 Microsoft Corporation。保留所有权利。

C:\Users\易小白>cd C:\

#不关闭assert前:

C:\>python 日常学习代码.py

Traceback (most recent call last):

File "日常学习代码.py", line 5, in

fun(0)

File "日常学习代码.py", line 3, in fun

assert n!=0,'n=%d' % n

AssertionError: n不能为0

#关闭assert后:

C:\>python -O 日常学习代码.py#使用命令-O启动关闭assert模式,是英文字母O

Traceback (most recent call last):

File "日常学习代码.py", line 5, in

fun(0)

File "日常学习代码.py", line 4, in fun

return 10/n

ZeroDivisionError: division by zero#只提示错误,不显示assert,跟不使用assert的报错一样

logging.info():记录错误,类似装饰器,并不影响程序本体

运用logging.info()可以达到使用print一样打印出一个变量,区别在于print显示的变量,只能在程序中删除print代码才能关闭,而logging.info()没有配置是不会执行的:

import logging

#logging.basicConfig(level=logging.INFO)

e='0'

n=int(e)

logging.info('n=%d' % n)

print(10/n)

print('end')

运行结果:

>>>

============================= RESTART: C:\日常学习代码.py ============================

Traceback (most recent call last):

File "C:\日常学习代码.py", line 6, in

print(10/n)

ZeroDivisionError: division by zero

>>>

从上述结果可以看出,输出结果跟普通程序报错结果一模一样,现在我们进行info的配置:

import logging

logging.basicConfig(level=logging.INFO)#配置好info,info的内容就相当于运行日志了,也就是一个装饰器

e='0'

n=int(e)

logging.info('n=%d' % n)

print(10/n)

print('end')

运行结果:

>>>

============================= RESTART: C:\日常学习代码.py ============================

INFO:root:n=0#可以看到配置好后,多了一个INFO的日志信息

Traceback (most recent call last):

File "C:\日常学习代码.py", line 6, in

print(10/n)

ZeroDivisionError: division by zero

>>>

使用pdb模式进行调试

python的默认模式不包含pdb模式,需要启动其他模式的话需要使用cmd启动,加上模式名,例如启动关闭assert模式,命令为-O,启动pdb模式的命令为-m pdb

Microsoft Windows [版本 10.0.18362.239]

(c) 2019 Microsoft Corporation。保留所有权利。

C:\Users\易小白>cd C:\

C:\>python -m pdb 日常学习代码.py

> c:\日常学习代码.py(3)()

-> e='0'

(Pdb) l#命令l(list),列出代码

1 #import logging

2 #logging.basicConfig(level=logging.INFO)

3 -> e='0'#当前位置,可以看到指针指向它

4 n=int(e)

5 #logging.info('n=%d' % n)

6 print(10/n)

7 print('end')

[EOF]

(Pdb) n#命令n,执行下一行,因为#内容不执行,所以下一行为n=int(e)

> c:\日常学习代码.py(4)()

-> n=int(e)

(Pdb)#继续执行下一行

> c:\日常学习代码.py(6)()

-> print(10/n)

ZeroDivisionError: division by zero#print(10/n)运行结果出现Error

> c:\日常学习代码.py(6)()#继续按回车后,会停留在出错的一行

-> print(10/n)

(Pdb)#继续执行下一行

--Return-- #执行结果为return,执行完成,程序会返回

(Pdb) q #命令q是退出

C:\>#退出到启动前的目录

pdb.set_trace()

前面我们是运用Python的pdb模式,可以单步执行,但错误在运行很多行后才出现时,就会很不方便,试想你先要按几百个回车才能找到错误,再解决错误,这样效率就会很低,这是我们可以只在可能出错的位置放置一个断点,这样python会自动在断点位置暂停并进入pdb调试模式,用c继续执行下一行,这样效率就提高了很多。

先设置断点:

import pdb

e='0'

n=int(e)

print('测试')

pdb.set_trace()#pyhon运行到这里会自动进入pdb模式

print('进入pdb模式')

print(10/n)

print('end')

运行结果:

>>>

============================= RESTART: C:\日常学习代码.py ============================

测试

> c:\日常学习代码.py(6)()

-> print('进入pdb模式')

(Pdb)

从上面的结果我们可以知道,这样可以直接在python的shell中进行pdb模式的交互。

>>>

============================= RESTART: C:\日常学习代码.py ============================

测试

> c:\日常学习代码.py(6)()

-> print('进入pdb模式')

(Pdb) l#list命令依旧正常

1 import pdb

2 e='0'

3 n=int(e)

4 print('测试')

5 pdb.set_trace()#pyhon运行到这里会自动进入pdb模式

6 ->print('进入pdb模式')

7 print(10/n)

8 print('end')

[EOF]

(Pdb) n#执行下一行,结果正常

进入pdb模式

> c:\日常学习代码.py(7)()

-> print(10/n)

(Pdb) n#运行下一行,出现Error,并输出错误信息

ZeroDivisionError: division by zero

> c:\日常学习代码.py(7)()

-> print(10/n)

(Pdb) n#程序出错,返回,并输出错误信息

--Return--

> c:\日常学习代码.py(7)()->None

-> print(10/n)

(Pdb) c#继续运行,输出整个程序的运行结果,结果跟没有设置断点的结果一样

Traceback (most recent call last):

File "C:\日常学习代码.py", line 7, in

print(10/n)

ZeroDivisionError: division by zero

>>>

文本调试(doctest模块的testmod功能)

在注释中写入程序在交互环境下,运行的例子,这些是可以作为调试文档,进行调试的:

def my_abs(n):

'''

>>> my_abs(-1.11)

1.11

>>> my_abs(1.12)

1.12

>>> my_abs(-1)

1

x=float(n)

if x>0:

return x

elif x<=0:

return -x

else:

raise ValueError()

if __name__=='__main__':#导入调试模块进行调试

import doctest

doctest.testmod()

这里讲一下上面的

if __name__=='__main__':

,它的作用是仅在当前模块中运行,当这个模块被其他程序导入时,其他程序并不会执行

if __name__=='__main__':

后面的内容,实际上没有它程序也能正常运行,但是当你将其导入到另一个程序时,很多时候你不希望执行调试,这时就必须加上它。建议都加上,作为一种标准。

上述代码的运行结果:

>>>

============================= RESTART: C:\日常学习代码.py ============================

**********************************************************************

File "C:\日常学习代码.py", line 7, in __main__.my_abs

Failed example:

my_abs(-1)

Expected:#测试期望值为1

1

Got:#获得的值为1.0,期望值和获得值不一致,报错

1.0

**********************************************************************

1 items had failures:

1 of 3 in __main__.my_abs

***Test Failed*** 1 failures.

>>>

我们发现测试出现了一个错误,但是看上去测试文档好像没有问题,-1的绝对值是1,实际上从测试结果可以知道,计算-1绝对值后的值为1.0,所以报错,将测试文本中的1改为1.0就正常,不会报错了。原因是我们使用了float()将数字浮点化,所以结果为1.0。

你可能感兴趣的:(python,调试模式)