异常处理

一.错误和异常

在编写程序时,难免会出现错误,而错误一般分为两种

1.1.语法错误(这种错误,根本过不了Python解释器的语法检测,必须在程序执行前就改正)

语法错误示范 

 1 #语法错误示范一
 2 if
 3 
 4 #语法错误示范二
 5 def test:
 6     pass
 7 
 8 #语法错误示范三
 9 class Foo
10     pass
11 
12 #语法错误示范四
13 print(haha
14 
15 语法错误示范

1.2.逻辑错误示范一

1 #用户输入不完整(比如输入为空)或者输入非法(输入不是数字)
2 num=input(">>: ")
3 int(num)

逻辑错误示范二

1 #无法完成计算
2 res1=1/0
3 res2=1+'str'

2.什么是异常

异常就是在程序运行时发生错误的信号,在Python中,错误触发如下

3.Python中的异常种类

在Python中不同的异常可以用不同的类型(Python中统一了类于类型,类型即类)去标识,不同的类对象标识不同的异常,一个异常标识一种错误

Python中常见的异常

 1 'ArithmeticError'  # 计算错误,算法错误
 2 'AssertionError'  # 断言错误,常用于测试
 3 
 4 'AttributeError'  #  属性错误
 5 'BaseException',   # 基本异常
 6 BlockingIOError'  # 阻塞错误
 7  'BrokenPipeError'  # 管道破裂错误
 8  'BufferError'  # 缓冲区错误
 9  'BytesWarning',  # 字节警告
10 'ChildProcessError',  # 子进程错误
11 'ConnectionAbortedError'  #  连接终止错误
12 'ConnectionError',   # 连接错误
13 'ConnectionRefusedError'  # 连接拒绝错误
14  'ConnectionResetError',  # 连接重置错误
15 'DeprecationWarning'  #  废弃警告
16 'EOFError'  # 文件终止错误
17 'Ellipsis'  # 省略错误
18  'EnvironmentError'  # 环境错误
19 'Exception'  # 异常
20  'False'  #
21 'FileExistsError'  #  文件存在 错误
22 'FileNotFoundError'  # 文件不存在  错误
23  'FloatingPointError'  # 浮点指针错误
24  'FutureWarning'  # 关于构造将来会有改变的警告
25 'GeneratorExit'  # 生成器发生异常来通知退出
26  'IOError'  #输入/输出操作失败
27 'ImportError'  # 导入模块/对象失败
28  'ImportWarning'  # 导入模块/对象警告
29  'IndentationError',  # 缩进错误
30 'IndexError'  # 索引错误,序列中没有该索引
31 'InterruptedError'  # 被中断的错误
32  'IsADirectoryError'  # 是一个目录错误
33 'KeyError'  # 映射中没有这个键
34  'KeyboardInterrupt'  # 用户终端执行(通常输入的是^c)
35  'LookupError'   # 无效数据查询基类
36  'MemoryError'  # 内存溢出错误
37 'NameError'  # 名字错误
38  'None'  # 空值
39  'NotADirectoryError'  # 不是目录错误
40  'NotImplemented'  #  方法没有实现
41  'NotImplementedError'  # 尚未实现的方法
42 'OSError'  # 操作系统错误
43 'OverflowError'  # 旧的关于自动提升为长整型(long)的警告
44  'PendingDeprecationWarning'  # 关于特性将会被废弃的警告
45  'PermissionError'  # 权限错误
46  'ProcessLookupError'  # 进程获取错误
47  'RecursionError'  # 递归错误
48  'ReferenceError'  # 弱引用试图访问已经垃圾回收了的对象
49 'ResourceWarning'  # 资源警告
50 'RuntimeError'  # 一般运行时的错误
51  'RuntimeWarning'  # 可疑的运行时的行为警告
52  'StopAsyncIteration'  # 停止异步迭代错误
53 'StopIteration'  # 迭代器没有更多的值
54 ,'SyntaxError'  #   语法错误
55  'SyntaxWarning'  # 语法警告
56  'SystemError'  # 系统错误
57  'SystemExit',   # 系统退出
58 'TabError'  # Tab和空格键混用
59  'TimeoutError'  # 时间超时错误
60  'True'  #
61  'TypeError'  # 对象类型错误
62  'UnboundLocalError',   # 访问未初始化的本地变量
63 'UnicodeDecodeError'  # Unicode解码时的错误
64 'UnicodeEncodeError'  # Unicode编码时的错误
65 'UnicodeError'  # Unicode相关的错误
66  'UnicodeTranslateError'  # Unicode转换时的错误
67  'UnicodeWarning',  # Unicode警告
68  'UserWarning'  # 用户代码生成警告
69 'ValueError'  # 传入无效的cans
70 'Warning'  # 警告的基类
71 'WindowsError'  # 系统调用失败
72  'ZeroDivisionError'  # 除数为0错误
73  '__build_class__'
74 '__debug__'
75 '__doc__'
76 '__import__',
77 '__loader__'
78 '__name__'
79 '__package__', 
80 
81 '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip

触发异常举例

触发IndexError

触发KeyError

触发ValueError

二.异常处理

2.1什么是异常处理?

Python解释器检测到错误,触发异常,也允许程序员自己触发异常

程序员编写特定的代码,专门用来捕捉这个异常,这段代码与程序的逻辑无关,与异常处理有关

如果捕捉成功进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃,这就是异常处理

2.2为什么要进行异常处理

Python解释器去执行程序,检测到了一个错误,触发异常,在异常触发后且没有处理的情况下,程序就在当前异常处终止,后面的代码就不会运行了,那么谁会去用一个运行着就突然崩溃的软件

所以你必须提供一种异常处理机制来增强你程序的健壮性和容错性

2.3任何进行异常处理?

首先必须知道,异常是由程序的错误引起的,语法上的错误跟异常处理无关,必须在程序运行钱就修正

一.使用if判断式

正常代码示例

# 第一段代码
num1 = input('1>>>')  # 输入一个字符串试试
int(num1)
# 第二段代码
num2 = input('2>>>')  # 输入一个字符串试试
int(num2)
# 第三段代码
num3 = input('3>>>')  # 输入一个字符串试试
int(num1)

使用if判断进行异常处理

num1=input('>>: ') #输入一个字符串试试
if num1.isdigit():
    int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴
elif num1.isspace():
    print('输入的是空格,就执行我这里的逻辑')
elif len(num1) == 0:
    print('输入的是空,就执行我这里的逻辑')
else:
    print('其他情情况,执行我这里的逻辑')

#第二段代码
# num2=input('>>: ') #输入一个字符串试试
# int(num2)

#第三段代码
# num3=input('>>: ') #输入一个字符串试试
# int(num3)

'''
问题一:
使用if的方式我们只为第一段代码加上了异常处理,针对第二段代码,你得重新写一堆if,elif等
第三段,你还得在写一遍,当然了,你说,可以合在一起啊,没错,你合起来看看,你的代码还能被看懂吗???
而这些if,跟你的代码逻辑并无关系,这就好比你在你心爱的程序中到处拉屎,拉到最后,谁都不爱看你的烂代码,为啥,因为可读性差,看不懂

问题二:
第一段代码和第二段代码实际上是同一种异常,都是ValueError,相同的错误按理说只处理一次就可以了,而用if,由于这二者if的条件不同,这只能逼着你重新写一个新的if来处理第二段代码的异常
第三段也一样
'''

使用if判断进行异常处理

总结:

1.if判断式的异常处理只能是针对某一段代码,对于不同的代码段相同类型的错误你需要写重复的if来进行处理。

2.在你的程序中频繁的写与程序本身无关,与异常处理有关的if,那么你代码的可读性就会变得极其的差。

3.这是可以解决异常的,只是存在1,2的问题,所以,不能妄下定论if不能用来异常处理

二:Python为每一种异常定制了一个类型,然后提供了一种特定的语法结构用来进行异常处理

2.1 基本语法

try:
    被检测的代码块
except 异常类型:
    try中一旦检测到异常,就执行这个位置的逻辑

2.2 异常类只能用来处理指定的异常情况,如果非指定的异常类则无法处理

1 s1 = 'hello'
2 try:
3     int(s1)
4 except IndexError as f:
5     print(f)

2.3 多分支

1 s1 = 'hello'
2 try:
3     int(s1)
4 except IndexError as f:
5     print(f)
6 except KeyError as f:
7     print(f)
8 except ValueError as f:
9     print(f)

2.4 万能异常,在Python中有一个万能异常,Exception,他可以捕获任意异常,即;

s1 = 'hello'
try:
    int(s1)
except Exception as f:
    print(f)

你可能会说既然有万能异常,那么我直接用上面的这种形式就好了,其他异常可以忽略了

你说的没错,但是应该分为两种情况去看

2.4.1。如果你想要的效果是,无论出现什么异常,我们都统一丢弃,或者使用同一段代码逻辑去处理他们,那么,你大胆去做把,只有一个Exception就足够了

1 s1 = 'hello'
2 try:
3     int(s1)
4 except Exception as f:
5     print(f)
6 
7 #如果你统一使用Exception,没错,是可以捕捉所有异常,但意味着你在处理所有异常时都使用同一个逻辑去处理(这里说的逻辑即当前expect下面跟的代码块)

2.4.2如果你想要的效果是,对于不同的异常我们需要定制不同的处理逻辑,那么就需要用到多分支了

1 s1 = 'hello'
2 try:
3     int(s1)
4 except IndexError as f:
5     print(f)
6 except KeyError as f:
7     print(f)
8 except ValueError as f:

2.4.3 也可以在多分支后来一个Exception

 1 s1 = 'hello'
 2 try:
 3     int(s1)
 4 except IndexError as f:
 5     print(f)
 6 except KeyError as f:
 7     print(f)
 8 except ValueError as f:
 9     print(f)
10 except Exception as f:
11     print(f)

5.异常的其他机构

 1 s1 = 'hello'
 2 try:
 3     int(s1)
 4 except IndexError as f:
 5     print(f)
 6 except KeyError as f:
 7     print(f)
 8 except ValueError as f:
 9     print(f)
10 # except Exception as f:
11 #     print(f)
12 else:
13     print('try内代码块没有异常就执行我')
14 finally:
15     print('无论异常与否,都会执行该模块,通常是进行清理工作')

6 主动触发异常

1 try:
2     raise TypeError('类型错误')
3 except Exception as f:
4     print(f)

7.自定义异常

 1 class EgonException(BaseException):
 2     def __init__(self,msg):
 3         self.msg = msg 6 
 8 raise EgonException('类型错误')

8.断言

 1 def test():
 2     '一堆逻辑'
 3     res = 1
 4     return 1
 5 res1 = test()
 6 assert  res1 == 1
 7 # 以下的n多代码要跟res1进行下一步处理
 8 # 如果assert  res1 != 1 就会抛出AssertionError,等同于
 9 if res1 != 1:
10     raise AssertionError

9.try..except的方式比较if方式的好处

try...except这种异常处理机制就是取代if那种方式,让你的程序在不牺牲可读性的前提下增强健壮新和容错性。

异常处理中为每一个异常都定制了异常类型,对于同一种异常,一个except就可以捕捉到,可以同时处理多段代码的异常,无需写多个if判断式,减少了代码,增强了可读性。

 1 # num1=input('>>: ') #输入一个字符串试试
 2 # if num1.isdigit():
 3 #     int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴
 4 # elif num1.isspace():
 5 #     print('输入的是空格,就执行我这里的逻辑')
 6 # elif len(num1) == 0:
 7 #     print('输入的是空,就执行我这里的逻辑')
 8 # else:
 9 #     print('其他情情况,执行我这里的逻辑')
10 
11 #第二段代码
12 # num2=input('>>: ') #输入一个字符串试试
13 # int(num2)
14 
15 #第三段代码
16 # num3=input('>>: ') #输入一个字符串试试
17 # int(num3)
18 
19 try:
20     #第一段代码
21     num1=input('>>: ') #输入一个字符串试试
22     int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴
23     #第二段代码
24     num2=input('>>: ') #输入一个字符串试试
25     int(num2)
26     #第三段代码
27     num3=input('>>: ') #输入一个字符串试试
28     int(num3)
29 except ValueError as e:
30     print(e)
31 
32 再看try...except的牛逼之处

使用try...except的方式

1.把错误处理和真正的工作分开来。

2.代码更易组织,更清晰,复杂的工作任务更容易实现。

3.更安全,不会因为一些小的疏忽而使程序意外崩溃了。

四。什么时候使用异常处理。

try...except应该尽量少用,因为他本身就是你附加给你的程序的一种异常处理的逻辑,与你的主要工作是没有 关系的

这种东西加多了,会导致你的代码可读性变差

而且异常处理根本就不是你2b逻辑的擦屁股纸,只有在有些异常无法预知的情况下,才应该加上try...except,其他的逻辑错误应该尽量修正。

原文地址:https://www.cnblogs.com/YingLai/p/6240535.html