Fork me on GitHub

Python基础-异常处理(except)

什么是异常?
当程序运行时发生了某些错误,这时就会引发异常。Python中用异常对象(exception object)来表示异常情况,如果异常对象并没有被处理,程序就会终止,并发出回溯(traceback)显示错误信息


环境及版本

1
2
3
Windows 10 x64
Python 2.7
Pycharm 4.5.1

重要内建异常

异常类名称 描述
Exception 常规异常的基类
KeyboardInterrupt 用户中断执行
OverflowError 数值运算超出最大限制
ZeroDivisionError 在除法或者取模操作时第二个参数为0时引发
AttributeError 特性引用或复制失败时引发
IOError 输入、输出错误时引发
ImportError 导入模块/对象失败
IndexError 在使用不错的索引时引发
NameError 找不到变量(名字)时引发
SyntaxError python代码语法错误
TypeError 内建函数应用于错误对象类型时引发
ValueError 内建函数应用于正确对象,但是该对象使用不合适的值时引发
UnicodeError unicode编码相关错误
Warning 警告类型的基类

异常处理


完整形式

1
2
3
4
5
6
7
8
9
10
11
12
13
try:  
有异常语句...
except <name1>:
处理name1异常的语句
except <name2>:
处理name2异常的语句
.
.
.
else:
没有触发异常执行的语句
finally:
无论有没有异常都会执行的语句

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
try:
x = input("Enter the first number: ")
y = input("Enter the second number: ")
print x / y
except TypeError, e:
print "Type Error " + e.message
except ZeroDivisionError, e:
print "ZeroDivisionError " + e.message
else:
print "No Error"
finally:
print "Finish"


# 结果
#(输入5、0)
Enter the first number: 1
Enter the second number: 0
ZeroDivisionError integer division or modulo by zero
Finish

#(输入d)
Enter the first number: d
Name Error name 'd' is not defined
Finish
  • 当发生错误没有用try/except时,错误就会被传播到调用的函数中;如果调用函数中也没有捕获异常,这些异常就会传递到程序的最顶层
  • Python会从头到尾以及从左到右查看except子句,然后执行第一个相符的except下的语句
  • except和else语句只会执行其中的一个,try捕获到异常时会进入except处理异常,try没有捕获到异常会进入else执行相应代码
  • finally无论是否捕获到异常,都会去执行里面的语句;通常是将释放资源、关闭IO流等操作放在里面

except多种形式

上述例子中except后跟的是异常的名字,except语句还有很多种写法

形式 描述
except: 捕捉全部异常
except name: 捕捉特定name的异常
except name as value: 返回一个异常对象赋值给value
except (name1,name2): 一个代码块中捕获多个异常
except (name1,name2) as value: 一个代码块中捕获多个异常,返回一个异常对象赋值给value
1
2
3
4
5
6
7
8
9
10
11
try:
x = input("Enter the first number: ")
y = input("Enter the second number: ")
print x / y
except ZeroDivisionError as msg:
print "ZeroDivisionError " + msg.message

# 结果(输入8、0)
Enter the first number: 8
Enter the second number: 0
ZeroDivisionError integer division or modulo by zero
1
2
3
4
5
6
7
8
9
10
try:
x = input("Enter the first number: ")
y = input("Enter the second number: ")
print x / y
except:
print "All Except"

# 结果(输入d)
Enter the first number: d
All Except
1
2
3
4
5
6
7
8
9
10
11
try:
x = input("Enter the first number: ")
y = input("Enter the second number: ")
print x / y
except (ZeroDivisionError,NameError) as msg:
print msg.message

# 结果(输入8、0)
Enter the first number: 8
Enter the second number: 0
integer division or modulo by zero

只用except:时请注意,这样捕获异常是危险的,因为它会隐藏所有程序员没有想到并且没有做好准备处理的错误;应该使用明确的异常类进行处理


手动引发异常

我们可以使用raise语句来手动引发异常

  • 为了引发异常,可以使用一个类(应该是Exception的子类)或者实例参数调用raise语句
  • 使用类时,程序会自动创建类的一个实例
1
2
3
4
5
6
7
# 实例
raise IOError

Traceback (most recent call last):
File "D:/My office/learning-python/learning_except/except_test.py", line 42, in <module>
raise IOError
IOError
1
2
3
4
5
6
7
# 实例
raise IOError("This is a IOError")

Traceback (most recent call last):
File "D:/My office/learning-python/learning_except/except_test.py", line 42, in <module>
raise IOError("This is a IOError")
IOError: This is a IOError

自定义异常

有些时候我们需要创建自己的异常类,这个类就像其他类一样,只要是确保从Exception类继承
不管是简介继承还是直接继承,也就是是继承其他内建异常类也是可以的
class SomeOneException(Exception): pass

1
2
3
4
5
6
7
8
9
10
11
class MyException(Exception):
def __init__(self,message):
self.message = message

try:
raise MyException("This is my exception class")
except MyException, e:
print e.message

# 结果
This is my exception class

with/as语句

在处理IO流的时候可以用这种方式简化异常处理

1
2
3
# 基本语法
with expression [as variable]:
code
  • 在这里的expression要返回一个对象,从而支持环境管理协议。如果选用的as字句存在时,此对象也可返回一个值,赋值给变量名variable.
1
2
3
4
5
# 实例

with open("test.txt") as message:
for msg in message:
print msg
  • 无论是否引发异常,文件都会被正确关闭

异常处理注意事项

  • 一个try就有一个except或多个except,不要只t捕获不处理
  • 慎用异常:1.找到python的内置异常 2.理解python的内置异常分别对应什么情况 3.阅读你的代码,找到你的代码里可能会抛出内置异常的地方 4.仅对这几行代码做异常处理
  • 假设你无法知道你的代码会抛出什么异常,那么你的异常处理便是无效的

参考:Python基础教程(第2版·修订版)


转载请注明出处


Thank you for your support.