[Python学习日记-71] Python 中的异常处理
[Python学习日记-71] Python 中的异常处理
简介
报错我们并不陌生,在编写程序与运行程序的时候经常会遇到报错(报错其实就是程序运行时发生错误的信号,基本可以和异常划上等号),这通常会导致程序的终止,导致后面的代码都无法运行,但有时候我们并不想因为一点错误就导致整个程序终止,而是想后面的代码继续运行,这个时候就需要用到 Python 中的异常处理了,在本篇当中我们将了解什么是异常,了解常见的异常种类,并掌握如何使用异常处理。
什么是异常
异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止),在 Python 中错误触发的异常如下
而错误分为两种,一是语法错误,二是逻辑错误,详细如下:
1、语法错误
这种错误根本过不了 Python 解释器的语法检测,必须在程序执行前就进行更正
# 语法错误示范一
if
# 语法错误示范二
def test:
pass
# 语法错误示范三
class Foo
pass
# 语法错误示范四
print(hai
代码输出如下:
2、逻辑错误
这种错误可能程序能正常运行,但是程序运行的过程中可能会出现错误导致程序终止
# TypeError:int 类型不可选代
for i in 3:
pass
# ValueError
num = input(">>: ") # 输入 hello
int(num)
# NameError
aaa
# IndexError
l = ['jove','aa']
l[3]
# KeyError
dic = {'name':'jove'}
dic['age']
# AttributeError
class Foo:pass
Foo.x
# ZeroDivisionError:无法完成计算
res1 = 1/0
res2 = 1 + 'str'
代码输出如下:
异常的种类
在 Python 中不同的异常可以用不同的类型(Python 中统一了类与类型,类型即类)去标识,一个异常标识一种错误,下面我们来介绍一下各种异常。
一、常见异常
异常类型 | 描述 |
---|---|
AttributeError | 试图访问一个对象没有的属性,例如 Foo.x,但是 Foo 没有属性 x |
IOError | 输入/输出异常,基本上是无法打开文件 |
ImportError | 无法引入模块或包,基本上是路径问题或名称错误 |
IndentationError | 语法错误的子类,可能代码没有正确对齐之类的 |
IndexError | 下标索引超出序列边界,例如当 x 只有三个元素,却试图访问 x[5] |
KeyError | 试图访问字典里不存在的键 |
KeyboardInterrupt | 程序运行时 Ctrl+C 被按下 |
NameError | 使用一个还未被赋予对象的变量 |
SyntaxError | Python 代码非法,代码不能编译,也可以说是语法错误 |
TypeError | 传入对象类型与要求的不符合 |
UnboundLocalError | 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它 |
ValueError | 传入一个调用者不期望的值,即使值的类型是正确的 |
二、其他异常
异常类型 | 描述 |
---|---|
ArithmeticError | 表示数学运算错误的异常,它是 ZeroDivisionError(除数为零错误)、FloatingPointError(浮点运算错误)、OverflowError(数值运算超出范围错误)、UnderflowError(数值运算结果过小错误)、AssertionError(断言错误)和 SystemExit(程序退出错误)的基类 |
AssertionError | 通常在使用 assert 语句时触发,用于检查某个条件是否为真,如果条件为假,就会抛出 AssertionError 异常 |
BaseException | 它是最通用的异常类型,在 Python 中是所有异常的基类 |
BufferError | 表示发生了与缓冲区操作相关的错误 |
BytesWarning | 表示在 byte 或 bytearray 的操作中发生了潜在的问题,例如将 bytes 或 bytearray 对象视为字符串对象进行操作 |
DeprecationWarning | 用于警告某个功能、模块或方法已被弃用,即将在未来的版本中被移除。当程序中使用了被弃用的功能时,Python 会发出该异常来提醒开发者 |
EnvironmentError | 表示基本环境错误,在 Python3 中已被移除,可以用 OSError 来替代 |
EOFError | 表示遇到了意外的文件末尾(End of File) |
Exception | 用于捕获并处理各种类型的异常 |
FloatingPointError | 表示浮点运算错误,例如 1.0/0 或者对负数进行平方根运算时会触发 |
FutureWarning | 用来警告用户有关将来版本中可能发生的变化、废弃方法或可能导致问题的代码,通常不会导致程序中断,但提醒开发者代码可能需要调整或更新 |
GeneratorExit | 当一个生成器对象被关闭时,但还有未处理的 yield 语句时会抛出该异常 |
ImportWarning | 表示在导入模块时出现的警告,可能模块或包中的内容有致潜在的问题或错误 |
LookupError | 用于处理查找相关的错误,它是 IndexError、KeyError、NameError、AttributeError、ImportError 这类查找类型的基类 |
MemoryError | 表示内存不足的错误 |
NotImplementedError | 表示某个方法或函数的实现尚未完成 |
OSError | 表示与操作系统相关的错误,例如文件找不到、文件无法打开、权限不足等都会抛出该错误 |
OverflowError | 表示数值溢出错误,例如使用 int 类型来表示一个大于最大整数值的数时就会抛出该错误 |
PendingDeprecationWarning | 表示某个功能在未来版本中可能会被弃用 |
RuntimeError | 表示在运行时发生的错误,通常用于指示代码中的逻辑错误 |
RuntimeWarning | 表示在运行时发生了一个警告,并不会立即终止程序运行 |
StandardError | 异常类型的基类,在 Python3 已被移除,被 BaseException 代替 |
StopIteration | 迭代器对象的异常,在迭代过程中用来表示迭代结束的信号 |
SyntaxWarning | 语法警告,Python 解释器在检测到代码中存在一些不符合语法规范的写法 |
SystemError | 表示一个内部错误,通常是由于解释器自身出现问题而引发的异常 |
SystemExit | 表示程序正常地退出 |
TabError | 表示在代码中出现了 Tab 和空格混用的错误 |
UnicodeDecodeError | 将字节数据解码为 Unicode 字符时出现的错误 |
UnicodeEncodeError | 将字符串进行编码时发生错误会出现的错误 |
UnicodeError | 表示 Unicode 编码相关的错误,例如包含无效的 Unicode 字符、解码错误、编码错误等 |
UnicodeTranslateError | 表示在转换字符串时出现的 Unicode 转换错误,例如目标编码不支持源字符串中的某些字符、源字符串包含无法映射到目标编码的字符、源字符串包含无效的编码序列 |
UnicodeWarning | 表示 Unicode 相关的警告,它是 UnicodeError 的子类 |
UserWarning | 表示一些用户定义的警告 |
Warning | 警告,指在代码执行过程中发生了一些不太严重的问题,但仍然需要引起注意 |
ZeroDivisionError | 表示除法运算(/ 或者 //)错误,例如10/0 或者 100//0 |
异常处理
一、初识 try...except...
为了保证程序的健壮性与容错性,即在遇到错误时程序不会崩溃,我们需要对异常进行处理,而异常处理分为两种情况,一是错误发生的条件是可预知的,二是错误发生的条件是不可预知的,下面我们来看看面对这两种情况应该如何处理
1、如果错误发生的条件是可预知的,我们需要用 if 进行处理:在错误发生之前进行预防
AGE = 10
while True:
age = input('>>: ').strip()
if age.isdigit():
age = int(age) # 如果这里输入的是非数字的就会出错
if age > AGE:
print('太大了')
elif age < AGE:
print('太小了')
elif age == AGE:
print('刚刚好')
break
else:
print('只能输入数字')
代码输出如下:
2、如果错误发生的条件是不可预知的,则需要用到 try...except...:在错误发生之后进行处理
try...except... 的基本语法为:
try:
被检测的代码块
except 异常类型:
try 中一旦检测到指定的异常类型,就执行这里面的代码
a.txt
1111
22
333
444
# try...except是错误已经出现了,但是不让错误呈现出来
f = open('a.txt','r',encoding='utf-8')
try:
print(next(f),end='')
print(next(f),end='')
print(next(f),end='')
print(next(f),end='')
print(next(f),end='')
print(next(f),end='')
except StopIteration:
print('出错啦')
f.close()
print('=====>1')
print('=====>2')
print('=====>3')
代码输出如下:
二、try...except... 详细用法
1、异常类只能用来处理指定的异常情况,如果非指定异常则无法处理
s1 = 'hello'
try:
int(s1) # ValueError
except IndexError as e: # 未捕获到异常,程序直接报错
print(e)
代码输出如下:
2、多分支的异常处理
被检测的代码块抛出的异常有多种可能性,并且我们需要针对每一种异常类型都定制专门的处理逻辑,如下
try:
print('=====>1')
name # NameError
print('=====>2')
l = [1,2,3]
l[100] # IndexError
print('=====>3')
d = {}
d['name'] # KeyError
print('=====>4')
except NameError as e:
print('----->',e)
except IndexError as e:
print('----->', e)
except KeyError as e:
print('----->', e)
print('====>after code')
代码输出如下:
发生 NameError 错误时
发生 IndexError 错误时
发生 KeyError 错误时
无错误发生时
3、万能的异常处理——Exception
被检测的代码块抛出的异常有多种可能性,并且我们针对所有的异常类型都只用一种处理逻辑那就可以使用 Exception 来处理所有异常了,如下
try:
print('=====>1')
name # NameError
print('=====>2')
l = [1,2,3]
l[100] # IndexError
print('=====>3')
d = {}
d['name'] # KeyError
print('=====>4')
except Exception as e:
print('异常发生啦: ', e)
print('====>after code')
代码输出如下:
结合多分支来使用,把 Exception 当做托底的异常处理
try:
print('=====>1')
name # NameError
print('=====>2')
l = [1,2,3]
l[100] # IndexError
print('=====>3')
d = {}
d['name'] # KeyError
print('=====>4')
except NameError as e:
print('----->',e)
except IndexError as e:
print('----->', e)
except KeyError as e:
print('----->', e)
except Exception as e:
print('统一的处理方法')
print('====>after code')
代码输出如下:
4、异常处理的其他机构(else、finally)
try:
print('=====>1')
# name
print('=====>2')
l = [1,2,3]
# l[100]
print('=====>3')
d = {}
# d['name']
print('=====>4')
except NameError as e:
print('----->',e)
except IndexError as e:
print('----->', e)
except KeyError as e:
print('----->', e)
except Exception as e:
print('统一的处理方法')
else:
print('在被检测的代码块没有发生异常时执行')
finally:
print('不管被检测的代码块有无发生异常都会执行')
print('====>after code')
代码输出如下:
finally 感觉和直接写在 try...except... 外的代码没什么区别,其实它的具体应用是在于回收资源的环节,例如文件操作完成后的 close() 操作,如下
try:
f=open('a.txt','r',encoding='utf-8')
print(next(f),end='')
print(next(f),end='')
print(next(f),end='')
print(next(f),end='')
print(next(f),end='')
print(next(f),end='')
except StopIteration as e:
print('----->', e)
finally:
f.close()
代码输出如下:
5、主动触发异常
class People:
def __init__(self,name,age):
if not isinstance(name,str):
raise TypeError('名字必须传入str类型')
if not isinstance(age,int):
raise TypeError('年龄必须传入int类型')
self.name = name
self.age = age
p = People('jove','28')
代码输出如下:
6、自定义异常
class MyException(BaseException):
def __init__(self,msg):
super(MyException, self).__init__()
self.msg = msg
def __str__(self):
return '<%s>' % self.msg
raise MyException('我自己的异常类型') # print(obj)
代码输出如下:
注意:代码当中 raise MyException(...) 相当于 print(obj),如果不在 MyException 类当中定义 __str__ 将不会按照我们的设想那样在异常当中显示我们输入的信息
7、断言——assert 条件
info = {}
info['name'] = 'egon'
info['age'] = 18
# 这是断言assert做的事
# if 'name' not in info:
# raise KeyError('必须有name这个key')
# if 'age' not in info:
# raise KeyError('必须有age这个key')
assert ('name' in info) and ('age' in info)
if info['name'] == 'egon' and info['age'] == 18:
print('welcome')
代码输出如下:
如果 name 和 age 都存在
如果 name 或者 age 其中一个不存在
8、总结 try...except...
- 把错误处理和真正的工作分开来
- 代码更易组织,更清晰,复杂的工作任务更容易实现
- 程序更安全,不至于由于一些小的错误而使程序意外崩溃
原文地址:https://blog.csdn.net/zjw529507929/article/details/144269241
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!