python编写异常处理_Python 简明教程 --- 23,Python 异常处理
要么做第一个,要么做最好的一个。
目录
我们在编写程序时,总会不自觉的出现一些错误,比如逻辑错误,语法错误和一些其它的运行时错误等。
逻辑错误: 这种错误不会导致程序崩溃,它不容易被发现,只有在执行结果不是我们预期的时候,才会被发现。
语法错误: 这种错误是不符合语法规定的错误,说白了,就是编译器或者解释器无法理解的代码。出现这种错误时,程序是不能运行的。
其它运行时错误: 这种错误是程序在运行的过程中出现的,一般情况下不会出现,但是极端情况下会出现,是程序编写者考虑不够周全导致的。
在写程序时一定要把所有的情况都考虑到,并且处理掉,不能有侥幸心理(认为某种情况不会出现)。在程序中,只要是有可能出现的情况,那就一定会出现。
程序员也喜欢将这些错误戏称为bug,bug代表软件系统中的漏洞或缺陷,bug需要修正,否则程序是无法正常运行的。重要的软件系统如果出现漏洞,会带来巨大的危害。因此,在软件初步完成后,要进行严格的,全面的测试,否则将漏洞百出。
Python 中提供了一套处理错误的机制,叫做异常。
比较普通的处理错误的方法,是使用if 语句 或断言assert来对各种情况进行判断,从而进行相应的处理。而异常是一种更加高级的处理错误的机制。
1,常见异常
我们来看一些Python 中常见的异常。
SyntaxError 异常
Python 语言有自己的语法格式和规则,如果我们没有遵守这些规则,将会出现异常:
>>> print('abc')- # 右括号后边有一个横线
File "", line 1
print('abc')-
^
SyntaxError: invalid syntax
上尖括号^指出了异常出现的的位置。
NameError 异常
如果我们使用了一个未定义的变量,将会出现该异常:
>>> print(a) # a 变量未定义
Traceback (most recent call last):
File "", line 1, in
NameError: name 'a' is not defined
ZeroDivisionError 异常
进行除法运算时,如果除数为0,将会该异常:
>>> 1 / 0 # 除数为 0
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division by zero
如果程序没有处理异常,在异常出现时,将会崩溃退出,Python 解释器会为你定位到异常出现的位置,有助于快速的解决异常。
2,处理异常
异常需要捕获,从而处理异常。如果在发生异常时,这个异常没有被捕获处理,这个异常将会一层一层的向上抛,直到这个异常被捕获处理,或者程序崩溃。
try except 语句
在Python 中使用try 语句块来捕获异常,在except 语句块中处理异常。
我们一般将有可能出现异常的语句放在try 语句块中,在except 语句块中编写处理异常的措施。
比如,我们有如下代码:
def hello(s):
print('hello %s' % s)
hello('123', 'abc')
其中hello 函数的定义是需要接收一个参数,而在调用时,传递了两个参数,运行此代码将出现如下异常:
Traceback (most recent call last):
File "Test.py", line 8, in
hello('123', 'abc')
TypeError: hello() takes 1 positional argument but 2 were given
代码在遇到异常时,会在异常代码处抛出异常,后边的代码将不会再执行。如果异常代码没有处理,程序将崩溃退出。
我们可以这样处理该异常:
try:
hello('123', 'abc')
except Exception as e:
print(e)
我们将调用语句放在了try 语句块中,这样就可以捕获异常。except 关键字的后边是要捕获的异常的名字,as 后边是捕获到的异常 e。在except 语句块中,我们只是将捕获到的异常打印了出来,运行该代码,结果如下:
hello() takes 1 positional argument but 2 were given
可见错误被打印了出来。我们还可以在打印错误之后,再正确的调用hello 函数:
try:
hello('123', 'abc')
except Exception as e:
print(e)
hello('123')
运行结果如下:
hello() takes 1 positional argument but 2 were given
hello 123
可见,运行到hello('123', 'abc') 时,出现异常,然后代码执行到except 语句块,print(e) 将错误打印出来,又执行了hello('123')。
打印异常是最简单的处理异常的方式,在工作中,我们会将异常信息记录在日志文件中,这样可以将异常记录下来,以便处理异常。
一般在捕获异常时,尽量只在try 语句块中编写有可能发生异常的代码,基本不会发生异常的语句不要写在try 块中,这样可以减少try 块中的代码量,有助于定位问题。
except 语句
except 关键字后边可以跟一个异常名字,也可以跟一组异常名字,一组异常时,将多个异常的名字写在一个元组中,语法如下:
except (Error1, Error2...):
pass
一个try 语句中,也可以包含多个except 语句块,语法如下:
try:
# 代码块
except Error1 as e:
# 处理 Error1
except Error2 as e:
# 处理 Error2
.
.
.
except:
e = sys.exc_info()[0])
pass
多个except 语句块时,Python 解释器会从上到下依次判断异常的类型,直到符合某个异常时,会执行对应的语句块中的代码,在该except 块之后的except 块将被忽略。
其中,最后一个except 块可以省略异常的名字,这种格式可以匹配任意的异常,在该块中,可以使用sys.exc_info()[0] 来获取异常。
在有多个except 语句块时,要注意,前边的异常的范围应该小于等于后边的异常的范围,否则,后边的except 块将没有意义。
else 语句
Python 中,try... except... 之后还可以有一个else语句块,except 语句块是在遇到异常时执行的,else 语句块是在没有遇到异常时执行的。
发生异常时,示例:
try:
hello('123', 'abc')
except Exception as e:
print('发生异常')
print(e)
else:
print('没有发生异常')
上面的代码中,执行到hello('123', 'abc') 时会发生异常,然后会进入到except 语句块,else 语句不会被执行,执行结果如下:
发生异常
hello() takes 1 positional argument but 2 were given
没有发生异常时,示例:
try:
hello('123')
except Exception as e:
print('发生异常')
print(e)
else:
print('没有发生异常')
上面代码中的try 语句块不会发生异常,那么except 语句就不会执行,else 语句会执行,结果如下:
hello 123
没有发生异常
注意:
else 语句的使用频率并不高。
finally 语句
finally 语句块无论是否异常都会被执行,该语句块经常用在需要关闭系统资源的情况下。
没有发生异常时,示例如下:
try:
hello('123')
except Exception as e:
print('发生异常')
print(e)
else:
print('没有发生异常')
finally:
print('执行了 finally 语句块')
上面代码中,try 语句块没有发生异常,else 与 finally 都被执行,except 语句块没有执行。运行结果如下:
hello 123
没有发生异常
执行了 finally 语句块
发生异常时,示例如下:
try:
hello('123', 'abc')
except Exception as e:
print('发生异常')
print(e)
else:
print('没有发生异常')
finally:
print('执行了 finally 语句块')
上面代码中,try 语句块发生异常,except 与 finally 都被执行,else 语句块没有执行。运行结果如下:
发生异常
hello() takes 1 positional argument but 2 were given
执行了 finally 语句块
注意:
else 语句块与finally 语句块可以同时存在,也可以同时不存在,也可以一个存在一个不存在,互不影响。
3,抛出异常
raise 异常
如果你捕获了一个异常,却不想彻底解决这个异常,而想将该异常向上层抛出,可以使用raise 关键字。
raise 用于抛出异常,其后可以跟一个异常对象,或者什么也不跟。
raise 后跟一个异常对象:
raise Exception('这里发生了错误')
raise 后什么也不跟:
try:
hello('123', 'abc')
except Exception as e:
print('发生异常')
raise
Python 解释器会记录最后一个发生的异常,raise 会将最后一个异常抛出。上面代码中的raise 相当于raise e。
assert 断言
assert 语句称为断言,就是判断某个表达式是否为真:
表达式为True 时,正常通过
表达式为False 时,抛出AssertionError 异常
示例如下:
表达式1 == 1为True,没有反应:
>>> assert 1 == 1
表达式1 == 0为False,抛出异常:
>>> assert 1 == 0
Traceback (most recent call last):
File "", line 1, in
AssertionError
4,Python 异常层次结构
Python 异常层次结构如下:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
可参考这里:
https://docs.python.org/3/library/exceptions.html#exception-hierarchy
这些都是内建异常,BaseException 是所有异常的父类,我们使用最多的是Exception 及其子类。可以使用help(类名)来查看每个类的详情。
5,自定义异常
有时候,我们需要定义自己的异常类,来满足自己的需求。
我们已经知道,Python 异常类有自己的层次结构,所有的类都直接或者间接继承了BaseException。因此,用户自定义的异常类,也需要满足这种层次结构。
一般情况下,自定义异常需要继承Exception 类。如下:
class MyError(Exception):
pass
MyError 类的使用方式,跟内建异常类的使用方式一样。你可以根据自己的需要,为MyError 类编写相应的构造方法,和其它类方法。
如果没有为MyError 编写构造方法,那么MyError 就继承了Exception 的构造方法。
6,调试错误
程序编写完成后不一定是正确的,当发现有错误时,就需要定位错误的位置。
最普遍,最简单的调错的方法就是打印某个变量,通过输出变量的值,来查看其是否是你想要的结果。
另一种比较高效,有力的调试代码的方式是单步调试,即是通过设置断点,深入到代码内部,一步一步的跟踪查看代码的执行结果是否正确,从而达到修正代码的目的。
在C 语言中有一个非常著名的工具叫做gdb,这是一款强大的调试工具。Python 中也有类似的一款工具叫做pdb,它使用起来要比gdb 简单许多。
在Python 中,pdb 是一个模块,所以,在使用之前要先使用import pdb 将该模块引入。然后,在需要调试代码的地方,使用pdb.set_trace() 方法来设置断点,在代码执行到此处时,Python 解释器就会从此处开始让你调式代码。
如下代码,文件名为Test.py:
#! /usr/bin/env python3
# 引入 pdb 模块
import pdb
def hello(s):
print('hello %s' % s)
# 设置断点
pdb.set_trace()
hello('python')
hello('java')
我们使用python3 来运行该程序,如下:
$ python3 Test.py
> ~/Test.py(12)()
-> hello('python')
(Pdb)
可以看到代码在hello('python')之前暂停并进入断点,控制台显示出(Pdb),我们可以在这个后面输入Python 代码或者pdb 支持的命令。
pdb 常用命令如下:
n:进行下一步代码,即单步执行
c:代码执行到下一个断点处,如果没有下一个断点,则执行到程序结束
s:在遇到函数时,使用s 命令,可以进入函数内部
l:列出当前语句周围的10行代码
p:用于输出变量的值,相当于print 函数
(完。)
推荐阅读:
欢迎关注作者公众号,获取更多技术干货。
python编写异常处理_Python 简明教程 --- 23,Python 异常处理相关推荐
- python 三引号_Python 简明教程 --- 4,Python 变量与基本数据类型
微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 任何一个人都会写出能够让机器理解的代码,只有好的程序员才能写出人类可以理解的代码. -- Marti ...
- python sorted下标_Python学习教程(Python学习路线):第七天-字符串和常用数据结构
Python学习教程(Python学习路线):字符串和常用数据结构 使用字符串 第二次世界大战促使了现代电子计算机的诞生,当初的想法很简单,就是用计算机来计算导弹的弹道,因此在计算机刚刚诞生的那个年代 ...
- python 优雅退出_Python学习教程:Python 使用 backoff 更优雅的实现轮询
我们经常在开发中会遇到这样一种场景,即轮循操作.今天介绍一个Python库,用于更方便的达到轮循的效果--backoff. Python学习教程:Python 使用 backoff 更优雅的实现轮询 ...
- python画四边形_python绘图教程-用python来绘制出四边形
原标题:python绘图教程-用python来绘制出四边形 python的应用有很多,其中还可以用python来绘制四边形,下面羽忆教程网为您分享如何用python来绘制四边形的详细步骤. pytho ...
- python 元组长度_Python 简明教程 ---11,Python 元组
微信公众号:码农充电站pro 软件工程的目标是控制复杂度,而不是增加复杂性. -- Dr. Pamela Zave 目录 我们在上一节介绍了Python 列表list 数据结构,本节来介绍一下元组tu ...
- python dict下标_Python基础教程:python的数据类型
python基础之五大标准数据类型 学习一门语言,往往都是从Hello World开始. 但是笔者认为,在一个黑框框中输出一个"你好,世界"并没有什么了不起,要看透事物的本质,熟悉 ...
- python两层循环 循环完整体一个_Python学习教程(Python学习路线):Python编写循环的两个建议...
原标题:Python学习教程(Python学习路线):Python编写循环的两个建议 Python学习教程(Python学习路线):给大家总结了两个Python编写循环的建议 循环是一种常用的程序控制 ...
- 【Python】【进阶篇】十二、Python爬虫的Xpath简明教程(十分钟入门)
目录 十二.Python爬虫的Xpath简明教程(十分钟入门) 12.1 Xpath表达式 12.2 Xpath节点 12.3 节点关系 12.4 Xpath基本语法 12.4.1 基本语法使用 12 ...
- Python re(正则表达式)简明教程
Python re(正则表达式)简明教程(Python3) 举个栗子 常用函数举例 按字母顺序查询模块
最新文章
- petaPar培训文档
- vb子程序未定义怎么改怎么办_提示子程序或函数未定义怎么修改。。。
- 编程中python怎么读-python之文件读写
- 《云计算》学习笔记1
- linux 安装库 编译提示-lcrypto 无法链接,缺少 crypto 库
- CodeForces - 1521D Nastia Plays with a Tree(树上最小路径覆盖)
- 中国剧本推理市场洞察2021
- 【CSS】【7】CSS的盒子模型
- 同事乱用分页 MySQL 卡爆,我真是醉了...
- 投射电子显微镜(TEM)
- puts与fputs的区别
- 空间句法(二)——Axwoman 6.0
- 服务器常用语言,计算机常用词汇--语言及服务器篇
- js实现全屏和退出全屏功能
- 工业控制计算机固态硬盘,工业控制电脑ssd固态硬盘怎么正确使用?
- java支持wingdings吗,[转]往JRE里添加新字体
- 云计算在商业智能运用中,主要存在哪些难点?
- Win7双网卡共享上网
- 「切图仔日常」浅谈加载动画两板斧
- 进阶篇:如何优化网站提升访问速度
热门文章
- php 编程祝新年快乐_AnyCodes:免费的在线编程神器
- dsp指令ixh_第一章 DSP入门教程(非常经典).pdf
- Spring入门详细教程(三)
- 机器人简化图画手绘图_床上用的扫地机器人,彻底清除细菌,不再担心酒店卫生问题...
- java compareto方法怎么排序的_深入理解Java中Comparable和Comparator排序
- jdbc封装mysql_用Java手动封装JDBC连接池(一)
- 企业研发人员配备比例_企业管理人员合理配置比例
- python如何查询数据库_Python数据库操作手册-数据库专栏,SQL Server
- 【深度学习入门到精通系列】Mean Iou
- python【数据结构与算法】多字段条件排序