Python学习7——异常
编写程序时,通常能够区分正常和异常情况。为了处理这些异常,可在每个可能出现异常的地方都使用上条件语句,但这样大大降低了程序的可读性,那么怎么解决哪?Python提供强大的替代解决方案——异常处理机制。
1、异常是什么?
Python使用异常对象来表示异常状态,并在遇到错误时引发异常,异常对象未被处理(或捕获)时,程序将终止并显示一条错误消息。
>>> 1/0
Traceback (most recent call last):
File "<pyshell#214>", line 1, in <module>
1/0
ZeroDivisionError: division by zero
2、让事情沿着指定的轨道出错
2.1 raise语句
要引发异常,可使用raise语句,并将一个类(必须是Exception的子类)或实例作为参数。将类作为参数时,将自动创建一个实例。
>>> raise Exception
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
raise Exception
Exception
#上方引发的是通用异常,没有指出出现了什么错误
>>> raise Exception('hyperdrive overload')
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
raise Exception('hyperdrive overload')
Exception: hyperdrive overload
#上方示例添加了错误消息hyperdrive overload
下方给出一些常用到的内置的异常类
| 类名 | 描述 |
| Exception | 几乎所有的异常类都是从它派生而来的 |
| AttributeError | 引用属性或者给它赋值失败时引发 |
| OSError | 操作系统不能执行指定任务时(如打开文件)引发,有多个子类 |
| IndexError | 使用序列中不存在的索引时引发,为LookuoError的子类 |
| keyError | 使用映射中不存在的键时引发,为LookupError的子类 |
| NameError | 找不到名称(变量)时引发 |
| syntaxError | 代码不正确时引发 |
| TypeError | 将内置操作或函数用于类型不正确的对象时引发 |
| ValueError | 将内置操作或者函数用于这样的对象时引发:其类型正确担包含的值不合适 |
| ZeroDivisionError | 在除法或者求模运算中的第二个参数为零时引发 |
2.2自定义的异常类
虽然内置异常类的范围足够广泛,但有的时候你可能想要自己创建异常类满足自己的代码需要。
那么如何创建自定义异常类哪?
就像创建其他类一样,不过必须直接或间接的继承Exception
>>>class someException(Exception):
pass
#当然,如果你乐意,也可以在自定义异常类中添加方法
3、捕获异常
try:
x=int(input("Please input x:"))
y=int(input("Please input y:"))
print(x/y)
except ZeroDivisionError:
print("The second numbercna't be zero!")
#一定要注意代码的缩进问题 Please input x:1
Please input y:0
The second numbercna't be zero!
3.1不用提供参数
捕获异常之后,如果要重新引发它(即继续向上传播),可调用raise契额不提供任何参数(也可显式地提供捕获到的异常,参见3.4).
这很有用,我们下面看一个例子:
>>> class MuffledCalculator:
mufflad=False
def calc(self,expr):
try:
return eval(expr)
except ZeroDivisionError:
if self.mufflad:
print("Division by zero is illegal")
else:
raise
#发生除零行为时,如果启用了“抑制”功能,方法cacl将(隐式地)返回None。换而言之,如果启用了“抑制”功能,就不应依赖返回值。 >>> calculator=MuffledCalculator()
>>> calculator.calc('10/2')
5.0
>>> calculator.calc('10/0')#关闭了抑制功能
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
calculator.calc('10/0')
File "<pyshell#17>", line 5, in calc
return eval(expr)
File "<string>", line 1, in <module>
ZeroDivisionError: division by zero >>> calculator.mufflad=True
>>> calculator.calc('10/0')
Division by zero is illegal
如你所见,关闭抑制功能时,捕获了异常 ZeroDivisionError 但继续向上传播它。
如果无法处理异常,在Except子句中使用不带参数的raise通常是不错的选择,但有时你可能想引发别的异常。在这种情况下,导致进入except子句的异常将被作为异常上下文存储起来,并出现在最终的错误消息中,如下所示:
>>> try:
1/0
except ZeroDivisionError:
raise ValueError Traceback (most recent call last):
File "<pyshell#27>", line 2, in <module>
1/0
ZeroDivisionError: division by zero
#在处理上述异常时引发了另一个异常
During handling of the above exception, another exception occurred: Traceback (most recent call last):
File "<pyshell#27>", line 4, in <module>
raise ValueError
ValueError
你可以使用raise...from...语句来提供自己的异常上下文,也可以使用None来禁用上下文。
>>> try:
1/0
except ZeroDivisionError:
raise ValueError from None Traceback (most recent call last):
File "<pyshell#32>", line 4, in <module>
raise ValueError from None
ValueError
>>>
3.2多个except语句
'
>>> try:
x=int(input("Please input x:"))
y=int(input("Please input y:"))
print(x/y)
except ZeroDivisionError:
print("The second numbercna't be zero!")
except ValueError:
print("That wasn't a number ,was it?") Please input x:1
Please input y:0
The second numbercna't be zero! Please input x:1
Please input y:e
That wasn't a number ,was it?
>>>
3.3一箭多雕
使用一个except 语句捕获多种异常,将异常类放在一个元组里。
>>> try:
x=int(input("Please input x:"))
y=int(input("Please input y:"))
print(x/y)
except (ZeroDivisionError,ValueError):
print("The numbers you input have bugs!") Please input x:1
Please input y:0 Please input x:3
Please input y:d
The numbers you input have bugs!
3.4捕获对象
要在except 语句中访问异常对象本身,可使用两个参数而不是一个参数(即便是你捕获多个异常时,也只是向except 提供了一个参数——一个元组。)需要让程序继续运行并记录错误(可能只是向用户显示)时,这很有用。下面这个示例,程序打印出现的异常并继续运行:
>>> try:
x=int(input("Please input x:"))
y=int(input("Please input y:"))
print(x/y)
except (ZeroDivisionError,ValueError)as e:
print(e) Please input x:1
Please input y:0
division by zero Please input x:1
Please input y:r
invalid literal for int() with base 10: 'r'
3.5一网打尽
即使程序处理了很多异常,但还是有漏网之鱼,例如上面程序什么都不输入就按回车键,仍然会出现一条错误信息,还有一些相关问题出现在什么地方的信息(栈跟踪),如下所示:
Please input x:
invalid literal for int() with base 10: ''
这种异常没有被捕捉到,因为你根本就没有预料这种情况,那这么做那?
>>> try:
x=int(input("Please input x:"))
y=int(input("Please input y:"))
print(x/y)
except :
print("Something wrong happened...")
这样更不行了,因为这不仅会隐藏你预料到的错误,更隐藏了你根本就没有想到的异常,你根本不知道哪出错了。。。
在大多数情况下,更好的选择是使用except Exceeption as e 并对异常对象进行检查。
3.6万事大吉时
有时候,在没有出现异常时执行一个代码块很有用。为此可以给try except语句加一个else语句。
同时,通过使用else 语句可以实现循环效果。
最后还有finally子句,可用在发生异常时执行清理作用。这个子句是和try子句配套的。
不管try子句中发生什么异常,都将执行finally子句
>>> while True :
try:
x=int(input("entern the x:"))
y=int(input("entern the y:"))
value=x/y
print("x/y is ",value)
except Exception as e:
print("Invalid input:",e)
print("Please try again")
else :
break
finally:
print("Everything is OK!") entern the x:1
entern the y:0
Invalid input: division by zero
Please try again
Everything is OK!
entern the x:1
entern the y:2
x/y is 0.5
Everything is OK!
4、异常和函数
函数和异常有着天然的联系,如果不处理函数中引发的异常,它将会向上传播到调用函数的地方。如果在那里也未得到处理,将会继续传播,直至到达主程序(全局作用域),如果主程序也不处理,那么程序将会终止并显示栈跟踪信息。下面看一个例子:
>>> def faulty():
raise Exception('Something is wrong') >>> def ignore_exception():
faulty() >>> def handle_exception():
try:
faulty()
except:
print("Exception handle") >>> ignore_exception()
Traceback (most recent call last):
File "<pyshell#39>", line 1, in <module>
ignore_exception()
File "<pyshell#30>", line 2, in ignore_exception
faulty()
File "<pyshell#27>", line 2, in faulty
raise Exception('Something is wrong')
Exception: Something is wrong
>>> handle_exception()
Exception handle
如你所见,faulty引发的异常依次从faulty和ignore_exception向外传播,最终导致显示一条栈跟踪消息。
调用handle_exception时,异常最终传播到handle_exception,并被这里的try/except语句处理。
5、异常之禅
异常处理并不复杂
6、只是警告(此处会用到几个函数,你可能不理解,但后面会介绍新学的函数)
有的时候,你只是想发出警告,指出情况偏离了正轨,可以使用warnings中的函数warn
>>> from warnings import warn
>>> warn("I've got a bad feeling about this.") Warning (from warnings module):
File "__main__", line 1
UserWarning: I've got a bad feeling about this.
#警告只显示一次,如果再次运行最后一行代码,将什么都不显示
如果其他代码在使用你的模块,可使用模块warnings 中的函数filterwarnings来抑制你发出的警告(或特定类型的警告),并指定要采取的措施,如"error"或者"ignore"
>>> from warnings import filterwarnings
>>> filterwarnings('ignore')
>>> warn('Anyone out there')
>>> filterwarnings("error")
>>> warn("Something is very wrong!")
Traceback (most recent call last):
File "<pyshell#49>", line 1, in <module>
warn("Something is very wrong!")
UserWarning: Something is very wrong!
如你所见,引发的异常为UserWarning,发出警告时,可指定将引发的异常(即警告类别),但必须是Warning的子类。
如果将警告转换为错误,将使用你指定的异常。
另外,还可根据异常来过滤掉特定类型的警告:
>>> filterwarnings("error")
>>> warn("This function is really old ......",DeprecationWarning)
Traceback (most recent call last):
File "<pyshell#59>", line 1, in <module>
warn("This function is really old ......",DeprecationWarning)
DeprecationWarning: This function is really old ......
>>> filterwarnings("ignore",category=DeprecationWarning)
>>> warn("Another deprecation warning.",DeprecationWarning)
>>> warn("Something else.")
Traceback (most recent call last):
File "<pyshell#63>", line 1, in <module>
warn("Something else.")
UserWarning: Something else.
>>>
小结:异常对象、引发异常、自定义的异常类、捕获异常、else子句、finally子句、异常和函数、警告
| 函数 | 描述 |
| warnings.filterwarnings(action,category=Warning,...) | 用于过滤警告 |
| warnings.warn(message,category=None) | 用来发出警告 |
Python学习7——异常的更多相关文章
- python学习笔记——异常
转自 http://www.cnblogs.com/rubylouvre/archive/2011/06/22/2086644.html Python内建异常体系结构 BaseException +- ...
- Python学习 之 异常
1.python中处理异常的方式 #coding:utf8 filename=raw_input("请输入你要操作的文件") try: f=open(filename) print ...
- 从0开始的Python学习016异常
简介 当你的程序不能正常运行的时候,Python会在控制台打印一段提醒,告诉你一个错误,这个错误就是异常. 错误 我在控制台写了一段无效的代码,将print()的括号去掉,在执行这条语句的时候,系统提 ...
- Python学习笔记异常
在程序代码中,可能会有各种错误的情况出现,且产生错误的结果是后面的代码都无法执行,即使是一点无关紧要的错误,如图: 在这样的情况下,我们需要异常处理,对程序代码中的错误抛出异常信息,且不影响后面的代码 ...
- 【python学习笔记】8.异常
[python学习笔记]8.异常 raise Exception: 抛出指定异常 try/except: 捕捉异常 except: 第一个参数是需要捕获的异常类型,可以是多个类型组成元组,第二个参数是 ...
- Python学习 Part6:错误和异常
Python学习 Part6:错误和异常 两种不同类型的错误:语法错误和异常 1. 语法错误 语法错误,也被称作解析错误: >>> while True print('Hello w ...
- python学习笔记5_异常
python学习笔记5_异常 1.什么事异常 Python使用异常对象(exception object) 来表示异常情况.遇到错误会发生异常. 如果异常对象未被处理或被捕捉,程序就会用所谓的回溯(t ...
- 转 Python3 错误和异常/ Python学习之错误调试和测试
########sample 0 https://www.cnblogs.com/Simon-xm/p/4073028.html except: #捕获所有异常 except: <异常名> ...
- 【Python学习之八】设计模式和异常
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 python3.6 一.设计模式1.单例模式确保某一个类只有一个实例, ...
随机推荐
- Django基础之命名URL和URL反向解析
在使用Django项目时,一个常见的需求是获得URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等). 人们强烈希望不要硬编码这些URL(费力 ...
- C++ 仿函数和适配器
本文从不断复杂的应用场景入手,来说明C++设计仿函数和适配器的原因,并深入源码来介绍仿函数和适配器的使用方法. 仿函数 现有一个vector,需要统计大于8的元素个数. 使用std::count_if ...
- CodeForces Good Bye 2016
A题,水题略过. B题,也水,但是想复杂了.只要运动超出[0,20000]的范围就算不可能了. C题,我自己的方法是解不等式,然后取最大的答案即可.代码如下: #include <stdio.h ...
- nginx的ngx_str_t
在nginx里的ngx_tr_t结构是字符串定义如下 typedef struct { size_t len; u_char *data; }ngx_str_t; 在给这样的结构体赋值的时候,ngin ...
- ARP 之 发送请求arp_solicit
概述 arp_solicit用来发送ARP请求,首先会根据ARP_ANNOUNCE参数来选取源地址,然后判断是否达到内核发送次数上限,未达到则调用内核arp_send_dst函数发送,如果达到上限,则 ...
- Qt串口通信专题教程
查看以前的教程:Qt编写串口通信程序全程图文讲解 查看Wincom和Lincom介绍:Qt跨平台串口通信软件Wincom与Lincom 下载软件,文档和源码:资源下载 ——————————————20 ...
- CodeIgniter安装和入门使用(一)
CodeIgniter是个轻量级功能也强大的框架,适合做自己做小项目用,本文介绍CodeIgniter的安装和使用.安装 官网链接http://codeigniter.org.cn/user_guid ...
- HearthBuddy Magnetic 磁力
https://hearthstone.gamepedia.com/Magnetic Magnetic is an ability exclusive to certain Mech minions ...
- PHP中的src32
crc32() 函数计算一个字符串的 crc32 多项式. 该函数可用于验证数据的完整性. 语法 crc32(str 参数 描述 string 必需.规定要计算的字符串. 说明 生成 string 参 ...
- CentOS服务器安装部署Java环境(jdk,tomcat)
第一步:卸载openjdk 用命令 java -version,如有下面的信息说明CentOS自带OpenJdk,没安装跳过这一步: 最好还是先卸载掉openjdk,再安装oracle公司的jdk.先 ...