# 异常概念
异常机制提高程序的健壮性,使用程序有更好的容错性。来看一个异常处理的样例:
import sys
try:
print(sys.argv[0])
a = int(sys.argv[1])
b = int(sys.argv[2])
c = a / b
print("a/b:%s" % c)
except ZeroDivisionError:
print("除数是0!")
except (ValueError,IndexError):
print("输入得到不是整数或者输入的参数不够!")
except Exception:
print("其他异常错误!")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 异常继承关系
注意捕获的异常应该由小到大,不同异常之间也是有继承关系的,应该先写最底层的异常,这样可以明确出问题后是哪方面的问题,异常之间的继承关系如下:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
引用自Python官方文档 Exception-hierarchy (opens new window)
# 访问异常信息
Python解释器决定调用某个except块时,会将异常对象赋值给except块后的异常变量,程序可通过该变量获取相关信息,所有的异常对象基本都包含下面几个属性和方法:
- args:返回异常的错误编号和描述字符串。
- errno:返回异常的错误编号。
- strerror:返回异常的描述字符串。
- with_traceback():获取异常的堆栈信息。
import sys
try :
f = open("temp.txt")
except Exception as e:
print(e.args)
print(e.errno)
print(e.strerror)
raise e.with_traceback(sys.exc_info()[2])
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# else和finally
看实例:
try:
result = 10/5
except ZeroDivisionError:
print("发生异常,除数是0!")
else:
print("正常执行")
1
2
3
4
5
6
2
3
4
5
6
else代码块的意义是只有在执行try代码块时没有发生异常才执行else代码块。
def TestFunc():
try:
a=10/0
return True
except ZeroDivisionError:
print("分母为0")
else:
print("程序正常执行")
finally:
print("执行finally代码块")
return False
print(TestFunc())
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
当代码块没有发生异常时吗,不会执行else代码块会直接执行finally代码块,当代码块发生异常时,执行完异常再执行finally代码块。
注意不要在finally代码块写return或raise语句,这样导致try代码块中的return失效。
# raise语句
我们可以主动触发异常,一般用于自定义的异常类,来看下raise的用法:
class MyException(Exception):pass
try:
print("this is a block!")
raise MyException
except MyException:
print("This is my exception!")
1
2
3
4
5
6
7
2
3
4
5
6
7
# 查看异常堆栈
import traceback
import sys
class MyExcept(Exception):pass
def F1():
F2()
def F2():
F3()
def F3():
F4()
def F4():
raise MyExcept("Test Exception Stack")
try:
F1()
except:
#print(traceback.format_exc())
traceback.print_exc(limit=2,file=open("temp.txt",'a'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 异常处理原则
异常处理需要有几个原则:
- 不要过度使用异常。不要把错误当成异常来处理。
- 不要使用过于庞大的try块。
- 不要忽略捕获的异常。