python异常处理
try...except
有时候写程序的时候,会出现一些错误或异常,导致程序终止。例如,做除法时,除数为0,会引起一个ZeroDivisionError
a=10
b=0
c=a/b
print("done")
运行结果:
Traceback (most recent call last):
...
ZeroDivisionError: division by zero
发现程序因为 ZeroDivisionError 而中断了,语句 print("done") 没有运行。为了处理异常,使用 try...except,更改代码:
a=10
b=0
try:
c=a/b
print(c)
except (ZeroDivisionError, TypeError) as e:
print(e)
print("done")
运行结果:
division by zero
done
这样程序就不会因为异常而中断,从而 print("done") 语句正常执行。
把可能发生错误的语句放在 try 模块里,用 except 来处理异常。except 可以处理一个专门的异常,也可以处理一组圆括号中的异常,如果 except 后没有指定异常,则默认处理所有的异常。每一个 try,都必须至少有一个 except
处理一组异常可以这样写(其中e代表异常的实例):
try:
pass
except (IOError, ZeroDivisionError) as e:
print(e)
Python 常见的标准异常类
异常名称 | 描述 |
---|---|
Exception | 所有异常的基类 |
AttributeError | 特征引用或者赋值失败时引发的 |
IOError | 试图打在不存在的文件(包括其他情况) |
IndexError | 使用序列中不存在的索引 |
KeyError | 使用映射中不存在的键 |
NameError | 找不到名字(变量) |
SyntaxError | 在代码为错误形式时引发 |
SystemExit | 系统异常退出 |
TypeError | 在内建操作或者函数应用与错误类型的对象时 |
ValueError | 正确的类型对象,但是对象使用不合适的值 |
ZeroDivisionError | 除法,第二参数为0 |
捕捉异常
基本形式:
try:
需要执行的操作
except 异常类 as e:
如果发生异常,执行以下代码
else:
如果没有发生异常,执行的命令
finally:
无论如何,都要执行的代码
- 注意 except as e 的写法,e 是一个变量,记录了异常的类,可以用 print 函数打印出来
- except 后面的异常类,建议写 Exception,这样就一定能捕获到异常。
捕获到异常,就不会去执行 else 模块
示例:
try:
name = input('Please input your name: ')
print('Hello %s' %name)
print(10/0)
except Exception as e:
print('Got an error ', e)
else:
print('OK')
finally:
print('Game over')
Please input your name: zhong
Hello zhong
Got an error division by zero
Game over
再举个例子:
import urllib.request
def main():
try:
response = urllib.request.urlopen("http://210.35.16.108")
# response = urllib.request.urlopen("https://www.baidu.com")
except Exception as e:
# raise
print(e)
else:
print('无异常则执行,有异常就不执行')
finally:
print('不管怎样,最后总会执行这行代码')
if __name__ == '__main__':
main()
结果:
<urlopen error [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。>
不管怎样,最后总会执行这行代码
[Finished in 21.5s]
捕获多个异常
方法一:
try:
需要执行的操作
except 异常类1 as e:
如果发生异常类1,执行以下代码
except 异常类2 as f:
如果发生异常类2,执行以下代码
else:
如果没有发生异常,执行的命令
finally:
无论如何,都要执行的代码
- except 后面的异常类,如果无需指定,直接写 Exception 即可。
- 如果需要明确指定异常的类,而且是多个类的情况下,可以使用多个 except 语句。
方法二:
try:
需要执行的操作
except (异常类1,异常2,异常3) as e:
如果发生异常,执行以下代码
else:
如果没有发生异常,执行的命令
finally:
无论如何,都要执行的代码
抛出异常
raise 关键字可以自主抛出异常,规则如下:
raise NameError([str])
- raise 后面跟异常的类,类括号里面,可以指定要抛出的异常示例,约详细越好
>>> raise NameError()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError
>>> raise NameError('bad name')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: bad name
例如:
# 当你输入的不是整数,它会报错(ValueError),但你输入的是一个整数后,它会输出你输入的整数。
Q = input("请输入一个整数:")
if type(Q) != type(1):
raise ValueError
else:
print(Q)
Q = input("请输入一个整数:")
if type(Q) != type(1):
raise leixingError("类型错误!")
else:
print(Q)
总结如下
except
语句不是必须的,finally
语句也不是必须的,但是二者必须要有一个,否则就没有try
的意义了。except
语句可以有多个,Python会按except
语句的顺序依次匹配你指定的异常,如果异常已经处理就不会再进入后面的except
语句。except
语句可以以元组形式同时指定多个异常,参见实例代码。except
语句后面如果不指定异常类型,则默认捕获所有异常,你可以通过logging或者sys模块获取当前异常。- 如果要捕获异常后要重复抛出,请使用
raise
,后面不要带任何参数或信息。 - 不建议捕获并抛出同一个异常,请考虑重构你的代码。
- 不建议在不清楚逻辑的情况下捕获所有异常,有可能你隐藏了很严重的问题。
- 尽量使用内置的异常处理语句来替换
try/except
语句,比如with
语句,getattr()
方法。