Python3之调试
程序能一次写完并正常运行的概率很小,基本不超过1%。总会有各种各样的bug需要修正。有的bug很简单,看看错误信息就知道,有的bug很复杂,我们需要知道出错时,哪些变量的值是正确的,哪些变量的值是错误的,因此,需要一整套调试程序的手段来修复bug。
第一种方法简单直接粗暴有效,就是用print()把可能有问题的变量打印出来看看:
err3.py
def foo(s):
n=int(s)
print('>>>n=%d' % n)
return 10 / n
def main():
foo('0')
main()
运行结果,在输出中可以查找到打印的变量值
>>>n=0
Traceback (most recent call last):
File "err3.py", line 7, in <module>
main()
File "err3.py", line 6, in main
foo('0')
File "err3.py", line 4, in foo
return 10 / n
ZeroDivisionError: division by zero
用print()最大的坏处是程序调试完毕需要删除,程序到处都是print(),运行结果也包含大量垃圾信息。所以,我们又有第二种方法
do_assert.py
断言
def foo(s):
n = int(s)
assert n != 0, 'n is zero!'
return 10 / n def main():
foo('0') main()
assert的意思是,表达式n!=0应该是True,否则,根据程序运行的逻辑,后面的代码肯定会出错
如果断言失败,assert语句本身就会抛出AssertionError
运行结果
Traceback (most recent call last):
File "do_assert.py", line 12, in <module>
main()
File "do_assert.py", line 10, in main
foo('0')
File "do_assert.py", line 6, in foo
assert n != 0, 'n is zero!'
AssertionError: n is zero!
程序中如果到处充斥着assert,和print()相比也好不到哪去。不过,启动Python解释器时可以用-O参数来关闭assert:
python3 -O do_assert.py
运行结果
Traceback (most recent call last):
File "do_assert.py", line 12, in <module>
main()
File "do_assert.py", line 10, in main
foo('0')
File "do_assert.py", line 7, in foo
return 10 / n
ZeroDivisionError: division by zero
关闭后,可以把所有的assert语句当成pass来看
logging
把print()替换成logging是第3种方式,和assert比,logging不会抛出错误,而且可以输出到文件
err4.py
import logging
#logging.basicConfig(level=logging.INFO)
s='0'
n=int(s)
logging.info('n=%d'%n)
print(10/n)
logging.info()就可以输出一段文本。运行,发现除了ZeroDivisionError,没有任何信息
Traceback (most recent call last):
File "err4.py", line 6, in <module>
print(10/n)
ZeroDivisionError: division by zero
修改增加配置
import logging
logging.basicConfig(level=logging.INFO)
s='0'
n=int(s)
logging.info('n=%d'%n)
print(10/n)
运行结果
INFO:root:n=0
Traceback (most recent call last):
File "err4.py", line 6, in <module>
print(10/n)
ZeroDivisionError: division by zero
这就是logging的好处,它允许你指定记录信息的级别,有debug,info,warning,error等几个级别,当我们指定level=INFO时,logging.debug就不起作用了。同理,指定level=WARNING后,debug和info就不起作用了。这样一来,你可以放心地输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。
logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。
pdb
第4种方式是启动python的调速器pdb,让程序以单步方式运行,可以随时查看运行状态
err5.py
#err5.py
s='0'
n=int(s)
print(10 / n)
启动
python3 -m pdb err5.py
以参数-m pdb启动后,pdb定位到下一步要执行的代码->s='0'
> /nas/scripts/python/learn-python3/samples/debug/err5.py(2)<module>()
-> s='0'
可以输入字母l来查看代码
(Pdb) l
1 #err5.py
2 -> s='0'
3 n=int(s)
4 print(10 / n)
输入n可以单步执行代码
(Pdb) n
> /nas/scripts/python/learn-python3/samples/debug/err5.py(3)<module>()
-> n=int(s)
> /nas/scripts/python/learn-python3/samples/debug/err5.py(4)<module>()
-> print(10 / n)
(Pdb) n
ZeroDivisionError: division by zero
> /nas/scripts/python/learn-python3/samples/debug/err5.py(4)<module>()
-> print(10 / n)
任何时候都可以输入p 加变量名查看变量
(Pdb) p s
'0'
输入q结束调试
这种通过pdb在命令行调试的方法理论上是万能的,但实在是太麻烦了,如果有一千行代码,要运行到第999行得敲多少命令啊。还好,我们还有另一种调试方法。
pdb.set_trace()
这个方法也是用pdb,但是不需要单步执行,我们只需要import pdb,然后,在可能出错的地方放一个pdb.set_trace(),就可以设置一个断点:
err6.py
#err6.py
import pdb
s='0'
n=int(s)
#运行到这来会自动暂停
pdb.set_trace()
print(10 / n)
运行代码,程序会自动在pdb.set_trace()暂停并进入pdb调试环境,可以用命令p查看变量,或者用命令c继续运行:
(base) [root@prd-zabbix debug]# python3 err6.py
> /nas/scripts/python/learn-python3/samples/debug/err6.py(7)<module>()
-> print(10 / n)
(Pdb) p n
0
(Pdb) c
Traceback (most recent call last):
File "err6.py", line 7, in <module>
print(10 / n)
ZeroDivisionError: division by zero
IDE
如果要比较爽地设置断点、单步执行,就需要一个支持调试功能的IDE。目前比较好的Python IDE有:
Visual Studio Code:https://code.visualstudio.com/,需要安装Python插件。
PyCharm:http://www.jetbrains.com/pycharm/
另外,Eclipse加上pydev插件也可以调试Python程序。
小结
写程序最痛苦的事情莫过于调试,程序往往会以你意想不到的流程来运行,你期待执行的语句其实根本没有执行,这时候,就需要调试了。
虽然用IDE调试起来比较方便,但是最后你会发现,logging才是终极武器。
Python3之调试的更多相关文章
- vscode设置python3.7调试环境(已更新)
汇总系列:https://www.cnblogs.com/dunitian/p/4822808.html#ai CentOS安装Python3.7:https://www.cnblogs.com/do ...
- Python3 调试技巧 —— 死循环
说下Python3不使用gdb的自身调试 前情提要:服务器莫名卡死,用网上的方法用gdb,下载了很多组件,包括那个libpython.py,都没什么用,看不到堆栈,也试了保存core文件等等 大事找官 ...
- CentOS安装Python3.7
vscode设置python3.7调试环境:https://www.cnblogs.com/dotnetcrazy/p/9095793.html 先下载一下压缩包(FTP传也一样):weget htt ...
- Pycharm同步远程服务器调试
Pycharm同步远程服务器调试 1.需要准备工具 xftp:上传项目文件 xshell:连接Linux系统调试,执行命令 PyCharm:调试python代码 这些软件可以自行网上搜索下载,也可以关 ...
- =============Python安装与使用================
用文本编辑器写Python程序,然后保存为后缀为.py的文件,就可以用Python直接运行这个程序了. Python的交互模式和直接运行.py文件有什么区别呢? 直接输入python进入交互模式,相当 ...
- 人脸检测及识别python实现系列(1)——配置、获取实时视频流
人脸检测及识别python实现系列(1)——配置.获取实时视频流 1. 前言 今天用多半天的时间把QQ空间里的几篇年前的旧文搬到了这里,算是完成了博客搬家.QQ空间里还剩下一些记录自己数学学习路线的学 ...
- Python 进阶 之 协程
协程的概念级描述(与线程对比):转自知乎 链接 线程有两个必须要处理的问题:一是碰着阻塞式I\O会导致整个进程被挂起: 二是由于缺乏时钟阻塞,进程需要自己拥有调度线程的能力. 如果一种实现使得每个线程 ...
- 转 Python3 错误和异常/ Python学习之错误调试和测试
########sample 0 https://www.cnblogs.com/Simon-xm/p/4073028.html except: #捕获所有异常 except: <异常名> ...
- 11 . Python3之异常,调试和测试
12.Python3入门之异常.调试和测试 在程序运行过程中,总会遇到各种各样的错误. 有的错误是程序编写有问题造成的,比如本应该输出整数结果输出了字符串,这种错误我们通常称之为bug,bug是必须修 ...
随机推荐
- html 摄像头画面水平翻转
<video onloadedmetadata="" id="inputVideo" autoplay muted playsinline>< ...
- jsp+ tinymce粘贴word
最近公司做项目需要实现一个功能,在网页富文本编辑器中实现粘贴Word图文的功能. 我们在网站中使用的Web编辑器比较多,都是根据用户需求来选择的.目前还没有固定哪一个编辑器 有时候用的是UEditor ...
- AGC 030 B - Tree Burning 结论+枚举
考试 T2,是一个脑筋急转弯. 最暴力的贪心是每次先选左,再选右,再选左..... 然而这么做在一些情况下是错的. 但是,我们发现我们的选法一定是 $LLLLRLRLRLRLR$ 或 $RRRRLRL ...
- learning java 正则表达式
var regStr = "Java is very good"; Matcher m = Pattern.compile("\\w+").matcher(re ...
- learning java java.time相关类
var clock = Clock.systemUTC(); System.out.println(clock.instant()); System.out.println(clock.millis( ...
- cube.js 学习(二)cube.js与 graphql2chartjs的比较
cube.js 是目前看到从设计以及理念上很不错的数据分析事件,graphql2chartjs 是hasura graphql-engine 团队开发 的一个类库基于graphql,以下做一些比较 c ...
- C结构体指针的初步使用
#include <stdio.h> #include <string.h> struct Books { char title[50]; //char author[100] ...
- Go程序员面试算法宝典-读后感1
这本书是讲解Go语言程序员面试笔试真题的书籍,讲的还不错,值得一看. 计算机技术博大精深,日新月异………………大神们疯狂的更新着技术,(我就更新,不服打我呀)虽然换汤不换药,又有几个人能精通基础,再延 ...
- 一次docker镜像的迁移
docker 镜像迁移 背景,本地测试环境要切到线上测试,镜像下载或编译都需要时间. 所以直接scp镜像过去来节省时间. save 相对于export会占用更多存储空间 被迁移服务器导出所有镜像 do ...
- 线程池(4)-参数-RejectedExecutionHandler
1.介绍 当线程池线程数大于最大线程数(maximumPoolSize)时,多余的任务,程序应该按照什么拒绝策略处理. 2.拒绝策略4个 AbortPolicy:丢弃任务,并抛出RejectedExe ...