Python有两种错误很容易辨认:语法错误和异常。
1 什么是异常?
异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。
一般情况下,在Python无法正常处理程序时就会发生一个异常。
如:有些是由于拼写、配置、选项等等各种引起的程序错误,有些是由于程序功能处理逻辑不完善引起的漏洞,这些统称为程序中的异常
异常是Python对象,表示一个错误。
当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。
常见异常如:
-
语法错误:SyntaxError:invalid syntax
2.变量名不存在:NameError:name 'b' is not defined
3.索引错误:IndexError: list index out of range
4.关键字错误:KeyError: 'c'
5.类型错误:TypeError: list indices must be integers, not str
6.参数传值错误:ValueError: invalid literal for int() with base 10: 'ab'(主要发生在函数里面)
7.属性错误:AttributeError: A instance has no attribute 'acc'
8.输入输出错误:IOError
解决方案◆
- 如果是拼写、配置等等引起的错误,根据出错信息进行排查错误出现的位置进行解决
- 如果是程序设计不完善引起的漏洞,根据漏洞的情况进行设计处理漏洞的逻辑;
2 错误处理
错误的出现,在程序中一般会有两种表现,一种是拼写错误,一种是程序执行过程中出现的错误,这样两种不同的错误应该怎么进行追踪和处理呢?
2.1. 拼写错误
常规情况下,拼写错误只是在简单的记事本等环境下进行开发时,容易手误产生拼写错误;当前开发环境下,我们经常使用一些半自动化的IDE开发工具,如pycharm等等,可以进行简单的程序关键字的拼写检查以及程序结构的检查,把一些简单的拼写问题掐死在萌芽之中
2.2程序运行时错误
程序运行过程中,也会出现各种各样的错误,对于错误的出现和提示信息必须有一个比较明确的掌握,才能在后续的程序开发中快速的开发并且修复问题,这里就会出现两个步骤
- 确定问题及问题出现的代码行
- 后续的问题处理【参考后面的异常处理】
3 异常处理方式
python程序中出现的异常信息,主要有两种处理操作方式
直接处理异常,保证程序正常执行
抛出异常,告知调用者出现的重要错误信息
捕捉异常可以使用try/except语句。
(1). 直接处理异常
c = int(input("请输入整数选项:")) print("用户输入了:%d" % c) 上述代码,正常执行过程中,如果用户输入了字母会出现ValueError异常错误信息 请输入整数选项:d Traceback (most recent call last): File "D:/Py1801_B/DATE2/python高级/多线程/text.py", line 18, in <module> c = int(input("请输入整数选项:")) ValueError: invalid literal for int() with base 10: 'd'
捕捉异常
# 捕捉异常 1 try: c = int(input("请输入整数选项:")) print("用户输入了:%d" % c) # 处理异常 except: print("出现了异常,用户输入了非法数据") 通过try捕捉可能出现的异常,如果出现异常~并不让程序直接崩溃退出,而是执行except中的代码块来处理出现的异常 上述代码中,可以通过except处理在try代码块中出现的任意异常 #捕捉异常2 try: c = int(input("请输入整数选项:")) print("用户输入了:%d" % c) # 处理指定异常 except ValueError: print("出现了异常,用户输入了非法数据") 可以在except关键字后面,添加指定的异常名称,来处理指定的异常;只有捕捉到该指定异常时except代码块才会执行
(2) .给异常信息定义别名
# 捕捉异常 try: c = int(input("请输入整数选项:")) print("用户输入了:%d" % c) # 处理指定的异常并获取异常信息 except ValueError as e: print("出现了异常,用户输入了非法数据", e)
上述代码中,在except中指定了处理的异常信息,并且通过as别名的方式将异常信息保存在了一个变量e中,后续可以通过变量e打印出现的异常信息
(3). 精确、同时处理多个异常
try: # 可能会出现文件找不到的异常:FileNotFoundError file = open("d:/test.txt", "r") # 可能会出现类型异常:ValueError c = int(input("请输入整数选项:")) print("用户输入了:%d" % c) # 指定需要处理的多个异常类型,包含在一个元组中 except (ValueError, FileNotFoundError) as e: print("出现了异常", e)
运行结果:
出现了异常 [Errno 2] No such file or directory: 'd:/test.txt'
如上述代码所示,将多个需要处理的异常信息,进行精确的异常捕捉来提高程序代码的容错性能
(4). 精确、分步处理多个异常
try: # 可能会出现文件找不到的异常:FileNotFoundError file = open("d:/test.txt", "r") # 可能会出现类型异常:ValueError c = int(input("请输入整数选项:")) print("用户输入了:%d" % c) # 指定需要处理的多个异常类型,可以通过多个except叠加完成 except ValueError as e: print("出现了非法输入异常", e) except FileNotFoundError as e: print("文件操作出现异常", e) except Exception as e: print("程序中出现了异常", e)
通过多个except叠加,进行异常的精确捕捉和精确处理
(5). 异常处理关键字finally
try: f = open("d:/oCam.rar", "rb") except FileNotFoundError as e: print("文件操作出现异常", e) except Exception as e: print("程序中出现了异常", e) finally: # finally模块中的代码,不论是否出现异常,最终都会执行的代码块 # 关闭文件,释放资源 f.close()
finally关键字比较特殊,主要是针对异常处理过程中的两种分支进行一个统一的处理
代码中根据是否出现异常会出现两个分支
分支一:代码中没有异常,try中的代码正常执行结束
分支二:代码中出现异常,从异常代码开始执行except中的代码
但是不论执行那个分支,最后进行统一的资源回收时必须执行相同的代码,所以finally关键字就出现了
(6). 异常处理关键字else
''' try: # 可能出现异常的代码 except ValueError as e: # 处理异常的代码 except FileNotFoundError as e: # 处理异常的代码 except: # 异常的通用处理 [else:] [# try中没有异常,才会执行的代码] [finally:] [# 无论try中是否出现异常,都会执行的代码] ''' try: f = open("d:/test.txt", "rb") except FileNotFoundError as e: print("文件操作出现异常", e) except Exception as e: print("程序中出现了异常", e) else: print("try中没有出现异常") finally: # finally模块中的代码,不论是否出现异常,最终都会执行的代码块 # 关闭文件,释放资源 f.close()
else关键字是一种语法糖,主要是将try中的代码进行了分离处理,将可能出现异常的代码和之后的代码分别安排在了不同的代码块中,主要目的是提高程序代码的可读性;但是实际项目操作过程中使用并不是很多,尤其是在try中或者except中出现了if语句的时候,else关键字使用反倒并不是尽如人意了。
(7). 抛出异常
# raise ValueError("出现错误") try: c = int(input("请输入选项:")) print("用户输入了选项:%d" % c) except ValueError as e: # 转换成一个比较清楚的异常 # 但是问题是:直接使用系统的异常名称,不是特别友好! raise ValueError("类型转换错误")
抛出异常:是异常处理中经常用到的手段,主要是给函数的调用者抛出异常信息,要求调用的开发人员
对传递的数据有一个比较强制的约束
抛出异常:比较常用的手段就是抛出自定义异常
因为系统的某些内建异常,解读起来还是比较有代沟的!在这样的情况下,将比较复杂的系统异常
转换成自定义的信息比较准确的异常数据展示,会更加友好!
4 自定义异常
自定义异常,是根据程序中功能的需要,定义的和项目本身结合比较紧密的个性化的异常信息;自定义异常应用比较广泛,主要分两个步骤进行操作
- 定义自定义异常
- 在合适的位置抛出异常
通常情况下,python中的自定义异常,都会选择从系统标准异常Exception进行继承实现,如下:
class MyException(Exception): def __init__(self, message): self.message = message def __str__(self): return “异常描述:%s” % self.message
抛出异常的操作比较简单,通过关键字raise直接抛出异常即可
raise MyException(“出现了自定义异常”)
结合案例:
class MyException(Exception): ''' 自定义异常 ''' def __init__(self, msg): self.msg = msg def __str__(self): return "异常描述:%s" % self.msg # 捕捉异常 try: # 用户输入数据 num1 = float(input("请输入第一个数据:")) num2 = float(input("请输入第二个数据:")) res = num1 / num2 # 处理类型异常 except ValueError: print("只能输入数字") raise MyException("只能输入数字,但是用户输入了其他非数字字符") # 处理0除数异常 except ZeroDivisionError: print("0不能做为除数") raise MyException("亲,不能用0做为除数的") # 正常结果 else: # 打印展示结果 print("除法运算结果:%.2f" % res) finally: print("计算过程结束")
运行结果:
请输入第一个数据:q Traceback (most recent call last): 只能输入数字 计算过程结束 File "D:/Py1801_B/DATE2/python高级/多线程/text.py", line 30, in <module> num1 = float(input("请输入第一个数据:")) ValueError: could not convert string to float: 'q' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "D:/Py1801_B/DATE2/python高级/多线程/text.py", line 36, in <module> raise MyException("只能输入数字,但是用户输入了其他非数字字符") __main__.MyException: 异常描述:只能输入数字,但是用户输入了其他非数字字符
5 python标准异常
异常名称 | 描述 |
---|---|
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
Exception | 常规错误的基类 |
StopIteration | 迭代器没有更多的值 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
FloatingPointError | 浮点计算错误 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
IOError | 输入/输出操作失败 |
OSError | 操作系统错误 |
WindowsError | 系统调用失败 |
ImportError | 导入模块/对象失败 |
LookupError | 无效数据查询的基类 |
IndexError | 序列中没有此索引(index) |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
NotImplementedError | 尚未实现的方法 |
SyntaxError | Python 语法错误 |
IndentationError | 缩进错误 |
TabError | Tab 和空格混用 |
SystemError | 一般的解释器系统错误 |
TypeError | 对类型无效的操作 |
ValueError | 传入无效的参数 |
UnicodeError | Unicode 相关的错误 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeTranslateError | Unicode 转换时错误 |
Warning | 警告的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
FutureWarning | 关于构造将来语义会有改变的警告 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
SyntaxWarning | 可疑的语法的警告 |
UserWarning | 用户代码生成的警告 |