Python基础 - 异常处理
异常处理, 平时用得非常多的, 即便程序的逻辑很简单, 但总是要考虑各种各样的情况出现, 为了使得程序更加健壮, 异和用户体验更好, 异常处理是必须掌握的. 同时, 在调试的时候, 捕捉异常也是一种最为常见的 找 bug 的方式呀.
场景无非就两个:
- 尝试捕捉异常: try ... except , 一般用万能的异常类 Exception
- 主动抛出异常: raise .....
常见异常
2 / 0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-2-8b4ac6d3a3e1> in <module>
----> 1 2 / 0
ZeroDivisionError: division by zero
2 + 'a'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-1bab65faeb88> in <module>
----> 1 2 + 'a'
TypeError: unsupported operand type(s) for +: 'int' and 'str'
{3, 4, 5} * 3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-d7437368bfef> in <module>
----> 1 {3, 4, 5} * 3
TypeError: unsupported operand type(s) for *: 'set' and 'int'
print(cj)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-5-230235b96338> in <module>
----> 1 print(cj)
NameError: name 'cj' is not defined
f = open('xxx.txt')
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
<ipython-input-6-82a0b92d4a44> in <module>
----> 1 f = open('xxx.txt')
FileNotFoundError: [Errno 2] No such file or directory: 'xxx.txt'
len(3)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-6b3b01eb5e19> in <module>
----> 1 len(3)
TypeError: object of type 'int' has no len()
list(3)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-f0568a1336f0> in <module>
----> 1 list(3)
TypeError: 'int' object is not iterable
异常处理结构
基本思路:先尝试运行代码,如果没有问题就正常执行,如果发生错误就尝试去捕获和处理,最后实在没有办法了才程序崩溃,从某个角度看,异常处理结构也属于选择结构的变形
try - except
try:
# 可能会依法异常的代码,先执行以下试试
except Exception [as reason]:
# 如果try 中的代码抛出异常,并被except捕获,就执行这里的代码
# 要求用户必须输入整数,不接受任何其他类型输入
while True:
try:
x = int(input("Please enter an integer: "))
print("You have input {0}".format(x)) # 我还是喜欢用 "You have input %d" % x
break
except Exception as result:
print(result)
print("Error")
Please enter an integer: vv
Erro
Please enter an integer: cj
Erro
Please enter an integer: 666
You have input 666
try - except - else
没有异常,执行else,异常则不走else, 类似 for/while - else 结构
try:
# 可能会引发异常的代码
except Exception [as result]:
# 用来处理异常的代码
else:
# 如果没有异常,就执行else, 否则不执行else
注意:不要把太多的代码放在try中,而是放真正可能会引发异常的代码
while True:
x = input("Please enter an integer: ")
try:
x = int(x) # 这才是最可能出错的地方
except Exception as result:
print("Error")
else: # 没有异常
print("You have input %d" % x)
break # 输入正确,退出循环
Please enter an integer: cj
Error
Please enter an integer: 666
You have input 666
try - except - finally
不论异常否,最后都会被执行,可用来做一些清理工作如,释放try代码申请的资源等等
try:
# 可能会引起异常的代码
except Exception:
# 处理异常的代码
finally:
# 不论try是否异常,都会执行这里的代码
def div(a, b):
try:
print(a / b)
except Exception:
# except ZeroDivisionError:
print('Error')
finally:
print("Anyway,i still say: 'hello world'")
div(3, 0)
Error
Anyway,i still say: 'hello world'
finally 子句也会发生异常
可做多种异常的异常处理结构
try:
# 可能会引起异常的代码
except Exception1:
# 处理异常类型1的代码
except Exception2:
# 处理异常类型2的代码
.....
except Exceptiongn:
# 处理异常类型n的代码
try:
x = float(input('请输入被除数:'))
y = float(input("请输入除数: "))
z = x / y
except ZeroDivisionError:
print("除数不能为0")
except TypeError:
print("二者都应为数值类型")
except NameError:
print("变量不存在")
else:
print(x, '/', y, '=', z)
请输入被除数:8
请输入除数: b
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-2-97c20fa0afa5> in <module>
1 try:
2 x = float(input('请输入被除数:'))
----> 3 y = float(input("请输入除数: "))
4 z = x / y
5 except ZeroDivisionError:
ValueError: could not convert string to float: 'b'
自定义异常类
num = input("请输入手机号:")
# 生成一个类,这个类可以用于保存异常的名字;必须要传Exception形参
class Phone(Exception):
pass
try:
if len(num) != 11:
# raise 定义异常的提示信息 异常类(提示的信息)
raise Phone("长度不够11位") # 给Phone异常,改变提示的信息
except Exception as result:
print(result) # result就是phone里面的提示语,是我们自定义的
# 什么时候用if?判断程序,确保里面程序不会有问题的时候
# 什么时候用try?觉得某段代码会报错才用try
class Div(Exception):
pass
try:
x = float(input('请输入被除数:'))
y = float(input("请输入除数: "))
z = x / y
raise Div("出错了哦, 好好检查下呢")
except Exception as result:
print(result)
else:
print(x, '/', y, '=', z)
请输入被除数:x
could not convert string to float: 'x'
断言assert 与上下文管理语句
assert 语句常用来在程序的某个位置确认某个条件必须满足.
assert仅当脚本的__ debug __ 属性值为True 时有效,一般只在开发和测试阶段使用,(程序编译为字节码时,assert语句将被删除
a = 3
b = 5
assert a == b, 'a must be equal to b'
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-9-2784da305078> in <module>
1 a = 3
2 b = 5
----> 3 assert a == b, 'a must be equal to b'
AssertionError: a must be equal to b
小结
-
程序出错是一件非常难以避免的事情
-
异常一般指程序运行时发生的错误
-
程序运行时出现错误会自动引发异常,程序员可通过raise语句显式引发异常
-
合理使用异常结构try-except-else-finally 可以使得程序更加健壮
-
try - except - else, 当程序异常则不会执行else; finally, 不论怎样都会执行,可用来清理try代码块的空间等工作
耐心和恒心, 总会获得回报的.