Python错误和异常的处理
1.错误和异常
使用python编程的时候难免会出现各种各样的错误,这些错误会使程序中断。好在python解释器会告诉你错误发生在什么位置以及错误产生的原因,便于我们进行修改和调试。有时候我们并不希望这种错误中断程序的运行,比如在使用爬虫访问网站的时候,我们并不希望因为服务器未响应的问题导致爬虫程序出现异常继而中断。于是通过异常处理能够忽略本次异常让程序继续运行下去。
2.Python标准异常总结
错误 | 描述 |
---|---|
AssertionError | 断言语句(assert)失败 |
AttributeError | 尝试访问未知的对象属性 |
EOFError | input()读取到EOF却没有接收到任何数据 |
FloatingPointErrot | 浮点计算错误 |
GeneratorExit | generator,close()方法被调用的时候 |
ImportError | 导入模块失败的时候 |
IndexError | 索引超出序列的范围 |
KeyError | 字典中查找一个不存在的关键字 |
KeyboardInterrupt | 用户输入中断键(Ctrl+c) |
MemoryError | 内存溢出(可通过删除对象释放内存) |
NameError | 尝试访问一个不存在的变量 |
NotImplementedError | 尚未实现的方法 |
OSError | 操作系统产生的异常(例如打开一个不存在的文件) |
OverflowError | 数值运算超出最大限制 |
ReferenceError | 弱引用(weak reference)试图访问一个已经被垃圾回收机制回收的对象 |
RuntimeError | 一般的运行时错误 |
StopIteration | 迭代器没有更多的值 |
SyntaxError | python的语法错误 |
IndentationError | 缩进错误 |
TabError | Tab和空格混合使用 |
SystemError | Python 编译器系统错误 |
SystemExit | python编译器进程被关闭 |
TypeError | 不同类型间的无效操作 |
ValueError | 传入无效的参数 |
ZeroDivisionError | 除数为零 |
3.抛出异常
我们可以通过raise关键字在程序的某个位置人为抛出一个异常。这种由我们主动引发异常的行为称为异常的抛出。
这里的异常类型最好跟发生错误的类型一致,当然如果不确定是哪种异常类型,也可以使用通用异常类型Exception表示。
raise [SomeException [, args [,traceback]]
第一个参数,SomeException必须是一个异常类,或异常类的实例
第二个参数是传递给SomeException的参数,必须是一个元组。这个参数用来传递关于这个异常的有用信息。
第三个参数traceback很少用,主要是用来提供一个跟中记录对象(traceback)
for i in range(10):
if i == 5:
raise Exception('当i == 5时抛出这个异常')
print(i)
输出结果:
0
1
2
3
4
Traceback (most recent call last):
File “C:\Users\冷月枫\Desktop\my.py”, line 3, in
raise Exception(‘当i == 5时抛出这个异常’)
Exception: 当i == 5时抛出这个异常
4.异常处理
Python程序在遇到异常的时候,如果不进行异常处理,那么程序就会结束运行。在多数情况下我们都希望程序能够打印出该异常并且继续运行程序,因此使用异常处理就显得十分重要了。
try-except
try:
程序部分
except 异常类型 as 别名:
异常处理部分
上面的语句其实和if-else语句非常相似,都属于分支型语句。程序首先会执行try的代码块,这部分代码也是程序的主体代码,而当主体代码产生异常时,就会执行except语句的代码,打印出异常的类型和提示信息。
name0 = [1,'b',4]
for i in name0:
try:
print(i+1)
except TypeError as t:
print('类型不同,不能相加!')
输出结果:
2
类型不同,不能相加!
5
多种异常
一个程序可能会产生多个异常,此时就可以使用多个except语句来处理。
try:
程序部分
except 异常类型1 as 别名1:
异常处理部分1
except 异常类型2 as 别名2:
异常处理部分2
except 异常类型3 as 别名3:
异常处理部分3
在上面的程序中,首先会执行try语句下面的程序部分,如果发现异常,就会执行第一个except语句查看是不是该异常类型,如果是则执行该异常类型下的语句,如果不是则继续查看下一个except语句,依次进行下去。
name0 = [1,'b',4]
for i in name0:
try:
print(i+1)
except StopIteration as s:
print('停止迭代异常')
except TypeError as t:
print('类型不同,不能相加!')
输出结果:
2
类型不同,不能相加!
5
一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组
name0 = [1,'b',4]
for i in name0:
try:
print(i+1)
except (StopIteration,TypeError) as s:
print('类型不同,不能相加!')
最后一个except子句可以忽略异常的名称,它将被当作通配符使用。你可以使用这种方法打印一个错误信息,然后再次把异常抛出。
name0 = [1,'b',4]
for i in name0:
try:
print(i+1)
except (StopIteration) as s:
pass
except :
print('类型不同,不能相加!')
try/except…else
try/except 语句还有一个可选的 else 子句,如果使用这个子句,那么必须放在所有的 except 子句之后。
else 子句将在 try 子句没有发生任何异常的时候执行。
name0 = [1,'b',4]
for i in name0:
try:
print(i+1)
except (StopIteration) as s:
print('迭代停止')
except TypeError:
print('类型不同,不能相加!')
else :
print('什么也没有错')#没有发生异常执行这一个
输出结果:
2
什么也没有错
类型不同,不能相加!
5
什么也没有错
try-finally 语句
finally子句是无论是否检测到异常,都会执行的一段代码。我们可以丢掉except子句和else子句,单独使用try…finally,也可以配合except等使用。
name0 = [1,'b',4]
for i in name0:
try:
print(i+1)
except (StopIteration) as s:
print('迭代停止')
except TypeError as t:
print('类型不同,不能相加!',t)
else :
print('什么也没有错')#没有发生异常执行这一个
finally:
print('我一定会执行')
print()#换行 每打印一个数字换一行
输出结果:
2
什么也没有错
我一定会执行
类型不同,不能相加! can only concatenate str (not “int”) to str
我一定会执行
5
什么也没有错
我一定会执行
5.两个特殊的处理异常的简便方法
断言(assert)
assert expression[,reason]
assert是断言的关键字。执行该语句的时候,先判断表达式expression,如果表达式为真,则什么都不做;如果表达式不为真,则抛出异常。reason跟我们之前谈到的异常类的实例一样。
assert len('love') == len('like')#长度是否相等
print('1')
assert 1 == 1
print('2')
assert 1 == 2,'1 is not equal 2'
print('3')
输出结果:
1
2
Traceback (most recent call last):
File “C:\Users\冷月枫\Desktop\my.py”, line 5, in
assert 1 == 2,‘1 is not equal 2’
AssertionError: 1 is not equal 2
我们可以看到,如果assert后面的表达式为真,则什么都不做,如果不为真,就会抛出AssertionErro异常,而且我们传进去的字符串会作为异常类的实例的具体信息存在。
上下文管理(with语句)
如果你使用try,except,finally代码仅仅是为了保证共享资源(如文件,数据)的唯一分配,并在任务结束后释放它,那么你就有福了!这个with语句可以让你从try,except,finally中解放出来!
with open('C:\\Users\\冷月枫\\Desktop\\my.py') as f:
for i in f:
print(i)
输出结果:
with open(‘C:\Users\鍐锋湀鏋玕\Desktop\my.py’) as f:
for i in f:
print(i)
1)打开文件C:\Users\冷月枫\Desktop\my.py
(2)将文件对象赋值给 f
(3)将文件所有行输出
(4)无论代码中是否出现异常,Python都会为我们关闭这个文件,我们不需要关心这些细节。
使用with语句来使用这些共享资源,我们不用担心会因为某种原因而没有释放他。但并不是所有的对象都可以使用with语句,只有支持上下文管理协议(context management protocol)的对象才可以
6.异常和sys模块
另一种获取异常信息的途径是通过sys模块中的exc_info()函数。该函数回返回一个三元组:(异常类,异常类的实例,跟中记录对象)
try:
1/0
except:
import sys
tuple = sys.exc_info()
print('返回的异常的三元组:',tuple,'\n')
for i in tuple:
print(i)
输出结果:
返回的异常的三元组: (<class ‘ZeroDivisionError’>, ZeroDivisionError(‘division by zero’), <traceback object at 0x000001622E9D5048>)
<class ‘ZeroDivisionError’>
division by zero
<traceback object at 0x000001622E9D5048>
7.用户自定义异常
class MyError(Exception):
def __init__(self,value):
self.value = value
def __str__(self):
return repr(self.value)
try:
raise MyError(2*2)
except MyError as m:
print('my except occurred,value',m.value)
print()
raise MyError('oop!')
输出结果:
my except occurred,value 4
Traceback (most recent call last):
File “C:\Users\冷月枫\Desktop\my.py”, line 11, in
raise MyError(‘oop!’)
MyError: ‘oop!’
8.迭代器中的异常处理
前面我们介绍了迭代器,当迭代器中的元素全部取出来的时候会引发一个停止迭代的异常StopIteration,这个异常会中断我们的程序,非常不友好。因此在这里我们就需要使用异常处理规避掉这个异常,让程序继续运行下去。
name0 = iter('luatao')
list1 = []#创建一个空的列表
try:
while True:
list1.append(next(name0))#忘列表中添加一个元素
except StopIteration as s: #当迭代完之后出现异常执行
print(list1)
print('迭代完成')
输出结果:
[‘l’, ‘u’, ‘a’, ‘t’, ‘a’, ‘o’]
迭代完成
又完成一个,收工。吃饭(饿擦求了)。