Fork me on GitHub

异常处理

本文是Python通用编程系列教程,已全部更新完成,实现的目标是从零基础开始到精通Python编程语言。本教程不是对Python的内容进行泛泛而谈,而是精细化,深入化的讲解,共5个阶段,25章内容。所以,需要有耐心的学习,才能真正有所收获。虽不涉及任何框架的使用,但是会对操作系统和网络通信进行全局的讲解,甚至会对一些开源模块和服务器进行重写。学完之后,你所收获的不仅仅是精通一门Python编程语言,而且具备快速学习其他编程语言的能力,无障碍阅读所有Python源码的能力和对计算机与网络的全面认识。对于零基础的小白来说,是入门计算机领域并精通一门编程语言的绝佳教材。对于有一定Python基础的童鞋,相信这套教程会让你的水平更上一层楼。

一 异常的介绍

1. 什么是异常

异常处理也就是处理异常,那么我们首先要知道什么是异常?
异常是错误发生的信号,程序一旦出错,如果程序中还没有相应的处理机制,那么该错误就会产生一个异常抛出来,程序的运行也随之终止

2. 异常由三分部构成

  1. 异常的追踪信息
  2. 异常的类型
  3. 异常的值


异常的类型就是异常的类,所以可以打印SyntaxError来查看

3. 异常的分类

语法异常

这类异常是在程序运行之前,Python解释器会通篇监测语法,发现错误,直接抛错,所以你会发现程序根本就没有执行,这种异常我们应该在程序运行前就改正,这也是最基本的素质。
逻辑异常:
索引异常:

键值对的键异常:

属性异常:

注意:

  1. 程序上面的代码出现异常,程序随之终止,下面的代码不再运行
  2. 一切皆对象,os 也是对象


注意下图的打印信息

0 不能做被除数异常:

文件找不到异常:

关闭的文件不能读写异常:

不是整型格式的字符串转化为整型异常:

整型不可迭代异常:

变量名未定义异常:
函数也有自己的数据类型,他其实也是变量

常用异常总结:

AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的

更多异常:

ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError

二 异常处理

1. 异常处理的格式


try 加缩进的代码块,这部分代码是尝试捕获异常的代码,except 加可以预测到的异常种类。如果发生异常,并且补捕获到了异常的种类,就会执行 except 下面缩进的代码块。如果没有异常捕捉失败,那么异常还会发生 ,整个程序就终止了,所以 except 后面的 error 要和你抛出的异常相匹配才可以

2. 异常处理多分支


如果我们的需求是既要记录每一种异常的种类,要指明具体的异常信息,就是用这中方式处理,但是如果我们没有这么精确的需求,也可以使用同一种逻辑来处理。

如果我们不需要考虑异常发生的种类,只要代码平稳过渡,那么我们可以使用万能异常

虽然使用万能异常并不能清除的知道异常的类型,但是我们把异常的值赋值给一个变量名(上面所讲的其他异常也可以赋值),代码如下:

既要捕获指定的异常,又要确保程序平稳过渡

3. try 与 else 联用:

else: 不能单独使用,必须与except连用,意思是:else的子代码块会在被检测的代码没有出现过任何异常的情况下执行

4. try 与 finally 组合:

无论有没有异常发生,finally 子代码都会执行

try:
    print('start.....')
    # x=1
    # # y
    # l=[]
    # l[3]
    # d={'a':1}
    # d['b']
    # import os
    # os.aaa
    print('end....')
except NameError as e:
    print('NameError: ',e)
except KeyError as e:
    print('KeyError: ',e)
except Exception as e:
    print('万能异常---》',e)
else:
    print('在被检测的代码块没有出现任何异常的情况下执行')
finally:
    print('无论有没有异常发生,都会执行')
print('other.....')

finally的子代码块中通常放回收系统资源的代码

try:
    f = open('a.txt', mode='w', encoding='utf-8')
    f.readline()
    # f.close() 
finally:
    f.close()
print('other....')

会报错,不要吃惊,文件打开后,没有关闭,Python内部的资源,会有自己回收机制去回收,但是程序只要抛错,如果没有 finally 后面的代码,文件是无法关闭的,这个系统资源就需要我们手动处理。

三 主动触发异常

1. raise 主动触发异常

上面讲到的是程序发生的我们不想让他发生的异常,我们已经知道怎么处理了,另外还有一种情况,我们也希望能够主动触发异常,来对使用者进行一定的限制。

print(TypeError)  # TypeError是一个类
obj = TypeError("类型错误")  # 这其实就是实例化对象的过程
print(obj)
class People:
    def __init__(self, name):
        if not isinstance(name, str):
            raise TypeError('用户名 %s 必须是str类型' % name)
        self.name = name
p = People(123)

2. assert 断言

试想一个场景,假如程序执行了很多代码到了第300行代码,而第300行代码得出的变量值是否为空,将关系到下面的代码是否运行,没有断言之前我们一般会这么处理

print('part1........')
print('part1........')
print('part1........')
print('part1........')
print('part1........')
students = ['Albert', 'Harden', 'Curry', 'Wade']
students = []
if len(students) <= 0:
    raise TypeError  # 这里也可以不传参数
print('part2.........')
print('part2.........')
print('part2.........')
print('part2.........')
print('part2.........')
print('part2.........')

使用断言:

print('part1........')
print('part1........')
print('part1........')
print('part1........')
print('part1........')
students = ['Albert', 'Harden', 'Curry', 'Wade']
# students = []
# if len(students) <= 0:
#     raise TypeError  # 这里也可以不传参数
assert len(students) > 0
print('part2.........')
print('part2.........')
print('part2.........')
print('part2.........')
print('part2.........')
print('part2.........')

3. 自定义异常

异常也就是一个类,那么我们当然可以自定义

class RegisterError(BaseException):  # 需要继承这个异常的基类BaseException
    def __init__(self,massage,username):
        self.massage=massage
        self.username=username
    def __str__(self):  # 自定义对象的打印格式
        return '<%s:%s>' %(self.username,self.massage)
print(RegisterError)
obj = RegisterError('注册失败','Albert')
print(obj)
# 这行代码就相当于先初始化对象,再打印这个对象
raise RegisterError('注册失败','Albert')
posted @ 2019-04-09 18:12  马一特  阅读(255)  评论(0编辑  收藏  举报