1.什么是异常
当python检测到一个错误时,解释器就会指出当前流已经无法执行下去,这是就出现了异常
通俗来说,异常就是当程序出现了错误,而这种错误又是在正常控制流以外的(未预见的),那么我们采取什么样的行为去处理这个错误,就是异常需要做的
这个行为分为两个阶段:
-首先是引起异常发生的错误
-然是检测(和采取可能的措施)的阶段
2.常见异常
当程序运行时,如果遇到未解的错误导致中止运行,这时候就会抛出异常,出现traceback消息
异常 | 描述 |
NameError | 未声明/初始化对象 |
IndexError | 序列中没有此索引 |
SyntaxError | 语法错误 |
KeyboradInterrupt | 用户中断执行 |
IOError | 输入/输出操作失败 |
3.try-except语句
定义了进行异常监控的一段代码,并且提供了处理异常的机制
>>> try:
... f=open("213")
... except FileNotFoundError:
... print('no such file')
...
no such file
可以看到try-except就是将是捕获异常的动作,提前写好可能执行失败的代码(在except FileNotFoundError:下)
except也可以写多个
>>> try:
... data=int(input('input a number'))
... except KeyboardInterrupt:
... print ('user cancelled')
... except ValueError:
... print ('you must input a number')
...
input a number : a
you must input a number
input a number : (Ctrl + D中断输入)
user cancelled
4.异常参数
异常也可以有参数,异常引发偶会被传递给异常处理器
当异常被引发后参数是作为附加帮助信息传递给异常处理器的
>>> try:
... 10/0
... except ZeroDivisionError as e:
... print(e)
...
division by zero
此处的e就是一个参数,经处理器处理后作为一个变量保存错误信息。可以在后面的代码中调用这个异常信息
5.try-except-else语句
在try范围中没有异常被检测到时,执行else子句
>>> try:
... result=100/int(input("number:"))
... except ZeroDivisionError as e:
... print(e)
... else:
... print(result)
...
number:20
5.0
如果剔除我们的异常捕获代码,就是如下格式,其实系统也会捕获异常。但是在企业级的项目中,异常捕获代码是程序员的家常便饭,为了使代码更加的稳健,捕获异常是必要的
>>> result=100/int(input("number:"))
number:0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
6.try-except-finally
finally是无论异常是否发生,是否捕获异常都会执行的代码区。比如发生这样的情况:
如果打开文件后,发生异常导致文物并没有关闭,可能会发生数据损坏,使用finally可以保证文件总是能正常关闭
>>> try:
... a=open("/mnt/123")
... except FileNotFoundError:
... print("no file")
... finally:
... a.closed()
7.引发异常raise
你可以用raise语句引发异常
格式为: raise 异常名:
>>> age=int(input("age:"))
age:130
>>> if not 0 < age < 120:
... raise ValueError("out of range")
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: out of range
8.断言
断言是一句必须等价于布尔值为真的判断,若发生异常意味着表达式为假
格式:assert 判断,"输出信息"
>>> assert 10 > 100,"Wrong"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: Wrong
9.try-except-else-finally相结合的脚本
要求:
- 提示用户输入一个数字作为除数
- 如果用户按下Ctrl+C或Ctrl+D则退出程序
- 如果用户输入非数字字符,提示用户应该输入数字
- 如果用户输入0,提示用户0不能作为除数
方案:
首先,执行try子句(在关键字try和关键字except之间的语句),输入数字,让这个数字被100整除,
- 1.如果没有异常发生,忽略except子句,try子句执行后,执行else子句和finally子句,最后执行 try 语句之后的代码结束整个程序。
- 2.如果在执行try子句的过程中发生了异常,异常的类型和 except 之后的名称相符,那么对应的except子句将被执行。然后执行finally子句,最后执行 try 语句之后的代码结束整个程序。
#!/bin/usr/env python3
try:
num=(int)(input("number: "))
result=100/num
except ValueError:
print("请输入数字")
except ZeroDivisionError:
print("不允许使用0")
except (KeyboardInterrupt,EOFError):
print("\nBye-bye")
else:
print(result)
finally:
print("done")print('end of program')
执行结果:
[root@myhost mnt]# python3 7.py
number: 21
4.761904761904762
done
end of program
[root@myhost mnt]# python3 7.py
number: 0
不允许使用0
done
end of program
[root@myhost mnt]# python3 7.py
number: l
请输入数字
done
end of program
需要注意的是:允许用户中断这个程序(使用Ctrl+C或Ctrl+D方法)。用户中断的信息会引发KeyboardInterrupt 和EOFError 这两种异常。
一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。
处理程序将只针对对应的try子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。
try except 语句只有一个可选的else子句,使用这个子句,必须放在所有的except子句之后。这个子句将在try子句没有发生任何异常的时候执行。
finally子句是无论异常是否发生,是否捕捉都会执行的一段代码,使用finally可以保证文件总是能正常的关闭
10.raise+assert,引发异常和断言异常
要求:
- 编写第一个函数,函数接收姓名和年龄,如果年龄不在1到120之间,产生ValueError异常
- 编写第二个函数,函数接收姓名和年龄,如果年龄不在1到120之间,产生断言异常
方案:
两个函数,分别有引发异常及断言异常的功能:
- 1.当set_age()函数调用名字与年龄两个实参时,如果年龄在0-120范围内,打印“bob is 25 years old”,如果年龄在0-120范围外,利用raise 语句抛出一个指定的异常
- 2.当set_age2()函数调用名字与年龄两个实参时,如果年龄在0-120范围内,表达式为true,打印“bob is 20 years old”,如果年龄在0-120范围外,表达式为Flase,利用assert 断言语句抛出一个指定的异常
- #!/usr/bin/env python3
- def set_age(name, age):
- if not 0 < age < 120:
- raise ValueError("age out of range.")
- print("%s is %s years old" % (name, age))
- def set_age2(name, age):
- assert 0 < age < 120, 'age out of range.'
- print("%s is %s years old" % (name, age))
- if __name__ == '__main__':
- set_age('bob', 25)
- set_age2('bob', 20)