文章目录
一、什么是异常?
在日常编程开发中,难免遇到错误,常见的错误有为两类:
1、语法错误:
Python在解析代码时发现代码不符合 Python 语法规则时,就会报出 SyntaxError 错误提示。例如:
print “Hello,World!”
我们知道,Python 3 已不再支持上面这种写法,所以在运行时,解释器会报如下错误:
SyntaxError: Missing parentheses in call to ‘print’.
语法错误是解释器无法解析的,因此,只有纠正语法错误,程序才能运行。
2、运行错误:主要是程序内部隐含逻辑问题造成的数据错误和程序运行时与系统的规则冲突造成的系统错误等。例如:
list1 = [i for i in 3]
上面这句代码是我写python第一个错误,主要是3 不是可迭代对象,因此不能循环输出 i
TypeError: ‘int’ object is not iterable
上图是代码运行时的输出结果:
Traceback 区域是:异常追寻信息,能指定到具体文件下面的行。
TypeError:是异常类,python中内置几十种异常类
蓝色区域为异常值,会告诉你出错产生错误的原因。
二、python异常类型
1、Python内置异常
BaseException # 所有异常的基类
+-- SystemExit # 解释器请求退出
+-- KeyboardInterrupt # 用户中断执行(通常是输入^C)
+-- GeneratorExit # 生成器(generator)发生异常来通知退出
+-- Exception # 常规异常的基类
+-- StopIteration # 迭代器没有更多的值
+-- StopAsyncIteration # 必须通过异步迭代器对象的__anext__()方法引发以停止迭代
+-- ArithmeticError # 各种算术错误引发的内置异常的基类
| +-- FloatingPointError # 浮点计算错误
| +-- OverflowError # 数值运算结果太大无法表示
| +-- ZeroDivisionError # 除(或取模)零 (所有数据类型)
+-- AssertionError # 当assert语句失败时引发
+-- AttributeError # 属性引用或赋值失败
+-- BufferError # 无法执行与缓冲区相关的操作时引发
+-- EOFError # 当input()函数在没有读取任何数据的情况下达到文件结束条件(EOF)时引发
+-- ImportError # 导入模块/对象失败
| +-- ModuleNotFoundError # 无法找到模块或在在sys.modules中找到None
+-- LookupError # 映射或序列上使用的键或索引无效时引发的异常的基类
| +-- IndexError # 序列中没有此索引(index)
| +-- KeyError # 映射中没有这个键
+-- MemoryError # 内存溢出错误(对于Python 解释器不是致命的)
+-- NameError # 未声明/初始化对象 (没有属性)
| +-- UnboundLocalError # 访问未初始化的本地变量
+-- OSError # 操作系统错误,EnvironmentError,IOError,WindowsError,socket.error,select.error和mmap.error已合并到OSError中,构造函数可能返回子类
| +-- BlockingIOError # 操作将阻塞对象(e.g. socket)设置为非阻塞操作
| +-- ChildProcessError # 在子进程上的操作失败
| +-- ConnectionError # 与连接相关的异常的基类
| | +-- BrokenPipeError # 另一端关闭时尝试写入管道或试图在已关闭写入的套接字上写入
| | +-- ConnectionAbortedError # 连接尝试被对等方中止
| | +-- ConnectionRefusedError # 连接尝试被对等方拒绝
| | +-- ConnectionResetError # 连接由对等方重置
| +-- FileExistsError # 创建已存在的文件或目录
| +-- FileNotFoundError # 请求不存在的文件或目录
| +-- InterruptedError # 系统调用被输入信号中断
| +-- IsADirectoryError # 在目录上请求文件操作(例如 os.remove())
| +-- NotADirectoryError # 在不是目录的事物上请求目录操作(例如 os.listdir())
| +-- PermissionError # 尝试在没有足够访问权限的情况下运行操作
| +-- ProcessLookupError # 给定进程不存在
| +-- TimeoutError # 系统函数在系统级别超时
+-- ReferenceError # weakref.proxy()函数创建的弱引用试图访问已经垃圾回收了的对象
+-- RuntimeError # 在检测到不属于任何其他类别的错误时触发
| +-- NotImplementedError # 在用户定义的基类中,抽象方法要求派生类重写该方法或者正在开发的类指示仍然需要添加实际实现
| +-- RecursionError # 解释器检测到超出最大递归深度
+-- SyntaxError # Python 语法错误
| +-- IndentationError # 缩进错误
| +-- TabError # Tab和空格混用
+-- SystemError # 解释器发现内部错误
+-- TypeError # 操作或函数应用于不适当类型的对象
+-- ValueError # 操作或函数接收到具有正确类型但值不合适的参数
| +-- UnicodeError # 发生与Unicode相关的编码或解码错误
| +-- UnicodeDecodeError # Unicode解码错误
| +-- UnicodeEncodeError # Unicode编码错误
| +-- UnicodeTranslateError # Unicode转码错误
+-- Warning # 警告的基类
+-- DeprecationWarning # 有关已弃用功能的警告的基类
+-- PendingDeprecationWarning # 有关不推荐使用功能的警告的基类
+-- RuntimeWarning # 有关可疑的运行时行为的警告的基类
+-- SyntaxWarning # 关于可疑语法警告的基类
+-- UserWarning # 用户代码生成警告的基类
+-- FutureWarning # 有关已弃用功能的警告的基类
+-- ImportWarning # 关于模块导入时可能出错的警告的基类
+-- UnicodeWarning # 与Unicode相关的警告的基类
+-- BytesWarning # 与bytes和bytearray相关的警告的基类
+-- ResourceWarning # 与资源使用相关的警告的基类。被默认警告过滤器忽略。
2、自定义异常实例(一)
Python中也可以自定义自己的特殊类型的异常,只需要要从Exception类继承(直接或间接)即可:
class SomeCustomException(Exception):
pass
3、自定义异常实例(二)
class MyError(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg
try:
raise MyError('类型错误')
except MyError as e:
print('My exception occurred', e.msg)
'''创建了一个MyError类,基类为Exception,用于在异常触发时输出更多的信息。
在try语句块中,抛出用户自定义的异常后执行except部分,变量 e 是用于创建MyError类的实例。'''
三、常用异常(初学者必记)
Exception:常见错误异常的基类
异常类 | 解释 |
---|---|
SyntaxError | 语法错误 |
KeyError | 试图访问字典里不存在的键 |
TypeError | 传入对象类型与要求的不符合 |
ValueError | 传入一个调用者不期望的值,即使值的类型是正确的 |
ImportError | 无法引入模块或包;基本上是路径问题或名称错误 |
AttributeError | 找不到对应对象的属性 |
IOError | 输入/输出异常 |
IndentationError | 代码没有正确对齐,SyntaxError的子类 |
NameError | 使用一个还未被赋予对象的变量 |
IndexError | 下标索引超出序列边界 |
四、异常捕获
1、try…except…语句
把可能发生错误的语句放在try模块里,用except来处理异常,每一个try,都必须至少对应一个except。此外,与python异常相关的关键字主要有:
关键字 | 说明 |
---|---|
try/except | 捕获异常并处理 |
pass | 忽略异常 |
as | 定义异常实例(except MyError as e) |
else | 如果try中的语句没有引发异常,则执行else中的语句 |
finally | 无论是否出现异常,都执行的代码 |
raise | (主动)抛出/引发异常 |
2、try…except…语法结构
try:
<语句> #运行别的代码
except <异常类>:
<语句> #如果在try部份引发了'name'异常
except <异常类> as <数据>:
<语句> #如果引发了'name'异常,获得附加的数据
else:
<语句> #如果没有异常发生
3、捕获所有异常实例
try:
l1 = [i for i in 3]
except :
print('所有异常!')
4、捕获指定异常实例
''''''
try:
with open("testfile", "rb")as fh:
fh.read()
except IOError as e:
print("Error: 没有找到文件或读取文件失败",e)
Error: 没有找到文件或读取文件失败 [Errno 2] No such file or directory: 'testfile'
5、万能异常捕获实例
try:
l1 = [i for i in 3]
except Exception as e:
print('万能异常捕获',e)
万能异常捕获 'int' object is not iterable
6、捕获多个异常及异常处理顺序
1、捕获多个异常
#=================多分支异常=========================
s1 = 'hello'
try:
int(s1)
except IndexError as e:
print('IndexError异常',e)
except KeyError as e:
print('KeyError异常', e)
except ValueError as e:
print('ValueError异常', e)
#================ 一个条件捕捉多种类型异常 =====================
s1 = 'hello'
try:
int(s1)
except (IndexError, KeyError, ValueError) as e:
print('IndexError, KeyError, ValueError异常', e)
IndexError, KeyError, ValueError异常 invalid literal for int() with base 10: 'hello'
2、异常处理顺序
try:
f=open('a.txt') # 异常一:IOERRor
g = (line.strip() for line in fff) # 异常二 :NameError
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
except NameError as e:
print('我是异常e', e)
except IOError as b:
print('我是异常b',b)
结果:我是异常b [Errno 2] No such file or directory: 'a.txt'
try中一旦检测到异常,就会找到except 中对应的异常类,执行异常类下的逻辑,如果异常类不存在,则报错。
7、异常语句 else的用法
try:
<语句>
except <异常名1>:
print('异常说明1')
except <异常名2>:
print('异常说明2')
else:
<语句> # try语句中没有异常则执行此段代码
8、异常语句 try…finally…的用法
try…finally…(如果有finally语句,可以不用except语句)
str1 = 'hello world'
try:
int(str1)
except IndexError as e:
print(e)
except KeyError as e:
print(e)
except ValueError as e:
print(e)
else:
print('try内没有异常')
finally:
print('无论异常与否,都会执行我')
invalid literal for int() with base 10: 'hello world'
无论异常与否,都会执行我
9、多层嵌套异常
在python中,异常可以多层嵌套,当内层代码出现异常时,指定异常类型不符,则向外传,相符则处理,不相符则则向外传,至最外层,运用默认处理方法进行处理,即停止程序,并抛出异常信息。
try:
try:
1/0
finally:
print('finally')
except:
print('ok')
五、异常处理语法规则
通过上面代码可以总结:
执行try下的语句,如果引发异常,则执行过程会跳到第一个except语句。
如果第一个except中定义的异常与引发的异常匹配,则执行该except中的语句。
如果引发的异常不匹配第一个except,则会搜索第二个except,允许编写的except数量没有限制。
如果所有的except都不匹配,则异常会传递到下一个调用本代码的最高层try代码中。
六、触发异常
1、语法格式
raise [Exception [, args [, traceback]]]
语句中Exception是异常的类型(例如ValueError),参数是一个异常参数值。该参数是可选的,如果不提供,异常的参数是"None"。最后一个参数是跟踪异常对象,也是可选的(在实践中很少使用)。
2、代码实例
def not_zero(num):
try:
if num == 0:
raise ValueError('参数错误')
return num
except Exception as e:
print(e)
not_zero(0)
七、传递异常
捕捉到了异常,但是又想重新引发它(传递异常),可以使用不带参数的raise语句即可:
class MuffledCalculator:
muffled = False
def calc(self,expr):
try:
return eval(expr)
except ZeroDivisionError:
if self.muffled:
print 'Division by zero is illegal'
else:
raise
参考博客: https://www.jianshu.com/p/35a668fa1e54
https://blog.csdn.net/sinat_38682860/article/details/96627791
https://www.cnblogs.com/IPrograming/p/Python_error_handler.html