python基础之错误、调试(异常处理)
在程序运行过程中,总会遇到各种各样的错误。
有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这种错误我们通常称之为bug,bug是必须修复的。
有的错误是用户输入造成的,比如让用户输入email地址,结果得到一个空字符串,这种错误可以通过检查用户输入来做相应的处理。
还有一类错误是完全无法在程序运行过程中预测的,比如写入文件的时候,磁盘满了,写不进去了,或者从网络抓取数据,网络突然断掉了。这类错误也称为异常,在程序中通常是必须处理的,否则,程序会因为各种问题终止并退出。
Python内置了一套异常处理机制,来帮助我们进行错误处理。
此外,我们也需要跟踪程序的执行,查看变量的值是否正确,这个过程称为调试。Python的pdb可以让我们以单步方式执行代码。
最后,编写测试也很重要。有了良好的测试,就可以在程序修改后反复运行,确保程序输出符合我们编写的测试。
一、错误处理
1、语法错误
python的语法错误或者称之为解析错:SyntaxError: invalid syntax
2、异常
python程序的语法是正确的,但在运行期间检测到的错误称为异常,大多数的异常都不会被程序处理,都以错误信息的形式展现出来;常见的类型有: ZeroDivisionError,NameError 和 TypeError。
1 异常处理:
2 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
3 IOError 输入/输出异常;基本上是无法打开文件
4 ImportError 无法引入模块或包;基本上是路径问题或名称错误
5 IndentationError 语法错误(的子类) ;代码没有正确对齐
6 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
7 KeyError 试图访问字典里不存在的键
8 KeyboardInterrupt Ctrl+C被按下
9 NameError 使用一个还未被赋予对象的变量
10 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
11 TypeError 传入对象类型与要求的不符合
12 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
13 导致你以为正在访问它
14 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
3、异常处理
高级语言通常都内置了一套try...except...finally...的错误处理机制,python也不例外。
异常处理的三种方式:
try:
print(a)
except:
print('Error')
#try...except...
try:
print(a)
except TypeError as e:
print(e)
except NameError as e:
print(e)
#try...except NAME_ERROR as E
try:
print(a)
except NameError as e:
print(e)
except:
print('Error')
finally:
print('hello')
#finally下的是,不管程序是否错误都执行的代码块
try:
# 主代码块
pass
except KeyError,e:
# 异常时,执行该块
pass
else:
# 主代码块执行完,执行该块
pass
finally:
# 无论异常与否,最终执行该块
pass
try语句按照如下方式工作;
- 首先,执行try子句(在关键字try和关键字except之间的语句)
- 如果没有异常发生,忽略except子句,try子句执行后结束。
- 如果在执行try子句的过程中发生了异常,那么try子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的except子句将被执行。最后执行 try 语句之后的代码。
- 如果一个异常没有与任何的except匹配,那么这个异常将会传递给上层的try中。
一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。
处理程序将只针对对应的try子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。
一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:
except (RuntimeError, TypeError, NameError):
pass
最后一个except子句可以忽略异常的名称,它将被当作通配符使用。
try except 语句还有一个可选的else子句,如果使用这个子句,那么必须放在所有的except子句之后。这个子句将在try子句没有发生任何异常的时候执行。
try:
a = 1
print(a)
except NameError as e:
print(e)
except:
print('Error')
else:
print('hello') #else里的代码块是在try内的代码没有发生错误的时候才执行
finally:
print('world') #finally里的代码块是不管try里的代码是否正确都执行
使用 else 子句比把所有的语句都放在 try 子句里面要好,这样可以避免一些意想不到的、而except又没有捕获的异常。
4、记录错误
如果不捕获错误,自然可以让Python解释器来打印出错误堆栈,但程序也被结束了。既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。
Python内置的logging模块可以非常容易地记录错误信息:
import logging
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
res = bar('0')
print(res)
except Exception as e:
# print(e)
logging.exception(e) #记录错误信息
main()
print('END')
同样是出错,但程序打印完错误信息后会继续执行,并正常退出。
5、抛出错误
因为错误是class,捕获一个错误就是捕获到该class的一个实例。因此,错误并不是凭空产生的,而是有意创建并抛出的。Python的内置函数会抛出很多类型的错误,我们自己编写的函数也可以抛出错误。只有在必要的时候才定义我们自己的错误类型。
捕获错误的目的只是记录一下,便于后续追踪。可以通过raise语句来实现:
try:
print(a)
except NameError as e:
print(e)
raise
raise语句如果不带参数,就会把当前错误原样抛出。此外,在except中raise一个Error还可以把一种类型的错误转化成另一种类型,只要是合理的转换逻辑就可以。
二、调试
程序能一次写完并正常运行的概率很小,基本不超过1%。总会有各种各样的bug需要修正。有的bug很简单,看看错误信息就知道,有的bug很复杂,我们需要知道出错时,哪些变量的值是正确的,哪些变量的值是错误的,因此,需要一整套调试程序的手段来修复bug。
1、简单直接、粗暴有效的就是用print()把可能有问题的变量打印出来看看
def foo(s):
n = int(s)
print('>>n = %d' % n)
return 10 / n
def main():
foo('0')
main()
用print()最大的坏处是将来还得删掉它,想想程序里到处都是print(),运行结果中会包含很多垃圾信息。
2、断言
凡是用print()来辅助查看的地方,都可以用断言(assert)来替代:
def foo(s):
n = int(s)
assert n != 0,'s is zero'
return 10 / n
def main():
foo('0')
main()
assert的意思是,表达式 n != 0应该是True,否则,根据程序运行的逻辑,后面的代码肯定会出错;如果断言失败,assert语句本身就会抛出AssertionError
启动python解释器时可以用-O参数来关闭assert,注意,“-O”时英文字母大写的O;关闭后,我们可以把所有的assert语句当成pass来看。
3、logging
把print()替换为logging是第三种方式,和assert比,logging不会抛出错误,而且可以输出到文件:
import logging
s = '0'
n = int(s)
logging.info('n = %d' %n)
print(10 / n)
logging允许你指定记录信息的级别,有debug,info,warning,error等几个级别,当我们指定level=INFO时,logging.debug就不起作用了。同理,指定level=WARNING后,debug和info就不起作用了。这样一来,我们就可以放心地输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。
logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。
4、pdb
启动python的调试器pdb,让程序以单步方式运行,可以随时查看运行状态。(-m pdb)
输入命令1来查看代码
输入命令n可以单步执行代码
输入命令p+变量名来查看变量
输入命令q结束调试,退出程序
5、pdb.set_trace()
这个方法也是用pdb,但是不需要单步执行,我们只需要import pdb,然后,在可能出错的地方放一个pdb.set_trace(),就可以设置一个断点
import pdb
s = '0'
n = int(s)
pdb.set_trace() #程序运行到这里会暂停进入调试模式
print(10 / n)
运行代码,程序会自动在pdb.set_trace()暂停并进入pdb调试环境,可以用命令p查看变量,或者用命令c继续运行
6、IDE [集成开发环境(integrated development environment)]
如果要比较爽地设置断点、单步执行,就需要一个支持调试功能的IDE。目前比较好的Python IDE有:
Visual Studio Code:https://code.visualstudio.com/,需要安装Python插件。
PyCharm:http://www.jetbrains.com/pycharm/
另外,Eclipse加上pydev插件也可以调试Python程序。
python基础之错误、调试(异常处理)的更多相关文章
- python 基础篇 错误和异常处理
语法错误 所谓语法错误,也就是你写的代码不符合编程规范,无法被识别与执行,比如下面这个例子: if name is not None print(name) If 语句漏掉了冒号,不符合 Python ...
- 转 Python3 错误和异常/ Python学习之错误调试和测试
########sample 0 https://www.cnblogs.com/Simon-xm/p/4073028.html except: #捕获所有异常 except: <异常名> ...
- Python 基础之面向对象之异常处理
一.认识异常 1.常用异常报错的错误类型 IndexError 索引超出序列的范围 KeyError 字典中查找一个不存在的关键字 Na ...
- Python 迭代器,错误、异常处理
迭代器 迭代器可以用来遍历字符串.列表.元组.集合.字典. myString="hello" myIter=iter(myString) ##iter()函数可以获取元素集的一个迭 ...
- Python基础——8错误、调试和测试
捕捉错误 try: print('try...') r = 10 / int('2') print('result:', r) except ValueError as e: print('Value ...
- Python基础(十一) 异常处理
在程序运行过程中,总会遇到各种各样的错误,有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这样的错误我们通常称之为BUG,BUG是必须修复的.在Python中内置了一套异常处理机 ...
- Python基础系列讲解——try_except异常处理机制
在Python编程中不可避免的会出现错误,在调试阶段出现语法之类的错误时,Pycharm会在Debug窗口提示错误,但是程序在运行时由于内部隐含的问题而引起错误,会导致程序终止执行.比如以下例程中,使 ...
- python基础-requests模块、异常处理、Django部署、内置函数、网络编程
网络编程 urllib的request模块可以非常方便地抓取URL内容,也就是发送一个GET请求到指定的页面,然后返回HTTP的响应. 校验返回值,进行接口测试: 编码:把一个Python对象编码转 ...
- 经常出现在python中的错误和异常处理
PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取 http://t.cn/A6Zvjdun 使用try except处理异常 上面的代码中,被除数是0,会引发ZeroDivisio ...
随机推荐
- DDD实战让中台和微服务的落地如虎添翼
微服务到底怎么拆分和设计才算合理,拆多小才叫微服务?有没有好的方法来指导微服务和中台的设计呢? 深入DDD的核心知识体系与设计思想,带你掌握一套完整而系统的基于DDD的微服务拆分与设计方法,助力落地边 ...
- 几十行代码实现ASP.NET Core自动依赖注入
在开发.NET Core web服务的时候,我们习惯使用自带的依赖注入容器来进行注入. 于是就会经常进行一个很频繁的的重复动作:定义一个接口->写实现类->注入 有时候会忘了写Add这一步 ...
- Netcore webapi action swagger response返回参数使用匿名类型
问题:action中返回匿名对象时,swagger只能按强类型生成返回值描述 解决办法:使用roslyn在内存中动态执行代码,使用json.net反序列化匿名对象,向swagger返回动态匿名对象 效 ...
- NLP入门学习中关于分词库HanLP导入使用教程
大家好,时隔多年再次打开我的博客园写下自己的经验和学习总结,开园三年多,文章数少得可怜,一方面自己技术水平局限,另一方面是自己确实想放弃写博客.由于毕业工作的原因,经常性的加班以及仅剩下少的可怜的休息 ...
- MySQL性能压力基准测试工具sysbench
1.sysbench介绍 这里介绍一款MySQL数据库的压力测试软件sysbench,用它来进行基准测试. sysbench 是一个开源的.模块化的.跨平台的多线程性能测试工具, 可以用来进行CPU. ...
- 支持多线程的Redis6.0来了
支持多线程的 Redis 6.0 版本于 2020-05-02 终于发布了,为什么 Redis 忽然要支持多线程?如何开启多线程?开启后性能提升效果如何?线程数量该如何设置?开启多线程后会不会有线程安 ...
- 构建基于表单配置的 Jenkins 测试项目(接口、UI、APP、Jmeter)
1. 第一个 hello world 项目 2. 构建自动触发的项目(接口测试) 1)新建测试项目(执行测试脚本) 2)新建 Maven 打包项目 3)手动执行构建 4)修改 Web 工程代码并 pu ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(九)——一步一步教你如何撸Dapr之OAuth2授权
Oauth2授权,熟悉微信开发的同学对这个东西应该不陌生吧.当我们的应用系统需要集成第三方授权时一般都会做oauth集成,今天就来看看在Dapr的语境下我们如何仅通过配置无需修改应用程序的方式让第三方 ...
- 【工具库】Java实体映射工具MapStruct
一.什么是MapStruct? MapStruct是用于代码中JavaBean对象之间的转换,例如DO转换为DTO,DTO转换为VO,或Entity转换为VO等场景,虽然Spring库和 Apache ...
- hdu4901 枚举状态(找集合对S(xor) ==T(and))
题意: 给你一个串数字,然后让你在这里面挑取两个集合S ,T,集合的要求是 (1)不能为空 (2)S集合的所有元素必须在T集合的左边 (3)S集合的XOR == T集合的AND 问 ...