第十三篇:python之异常处理

什么是异常

异常就是程序运行时发生错误的信号,Python遇到错误后,会引发异常。如果异常对象并未被处理或捕捉,则程序就会用所谓的回溯(Traceback,一种错误信息)来终止执行。

为了保证程序的健壮性与容错性,即在遇到错误时程序不会崩溃,我们需要对异常进行处理。

下面编写一个同样功能的代码,对比做异常处理和不做异常处理的区别。

'''不做异常处理'''
num = int(input('请输入数字>>>')) #当输入的非数字时,则会触发异常,终止程序执行,下面的代码不会被执行,导致程序崩溃。
print('你输入的整数是:{}'.format(num))

 如果发生的错误是可预知的,我们可以用if语句进行处理:在错误发生之前进行预防。

'''做异常处理'''
num = input('请输入数字>>>') #当输入的非数字时,则会触发异常,终止程序执行,下面的代码不会被执行,导致程序崩溃。
if num.isdigit():
    print('你输入的整数是:{}'.format(int(num)))
else:
    print('你输入的不完全是数字。')

python的异常处理机制

 在所有的程序中,都会遇到异常,有些异常是代码编写的时候产生的,在前期过程中可能会直接导致程序无法运行。这一类的异常,在编写代码的时候,程序可以直接排查修改。但有些异常,是在程序运行过程中产生的,可能是与用户交互获取的数据无法识别,也或者是网络请求失败导致程序无法继续等等不可预知的异常。为了防止程序崩溃,这一类的错误,就需要程序员在编写的时候提前考虑到并进行相应的异常处理。每一门语言基本都有自己相应的异常防御机制,python尤其如此,不仅给了错误调试语句,还提供了庞大的内置异常类,让我们可以精准的针对不同异常给出不同的处理方式。

 异常分类

异常名称 描述
AssertionError 断言语句失败
AttributeError 对象没有这个属性
EOFError 没有内建输入,到达EOF 标记
EnvironmentError 操作系统错误的基类
IOError 输入/输出操作失败
WindowsError 系统调用失败
RuntimeError 一般的运行时错误
OverflowWarning 旧的关于自动提升为长整型(long)的警告
OSError 操作系统错误
Warning 警告的基类
DeprecationWarning 关于被弃用的特征的警告
FutureWarning 关于构造将来语义会有改变的警告
ImportError 导入模块/对象失败
LookupError 无效数据查询的基类
IndexError 序列中没有此索引(index)
MemoryError 内存溢出错误(对于Python 解释器不是致命的)
NameError 未声明/初始化对象 (没有属性)
OverflowError 数值运算超出最大限制
SyntaxWarning 可疑的语法的警告
ZeroDivisionError 当除运算或模零在所有数值类型运算时引发
PendingDeprecationWarning 关于特性将会被废弃的警告
RuntimeWarning 当生成的错误不属于任何类别时引发
UnicodeEncodeError Unicode 编码时错误
UserWarning 用户代码生成的警告
UnicodeTranslateError Unicode 转换时错误
UnboundLocalError 访问未初始化的本地变量
ReferenceError 弱引用试图访问已经垃圾回收了的对象
KeyError 映射中没有这个键

异常捕获

异常:是指在程序执行过程中发生的一个事件,会影响程序的正常运行,当程序运行时系统接受到异常对象时,会寻找能处理这异常的代码并把当前异常对象交给其处理。所以一般需要进行捕获异常并处理。异常的捕获使用try/except/finally语句进行捕获操作。

处理异常的语法结构:

'''异常处理'''
try:
    '''被检测的代码块'''
    num = input('请输入数字>>>')
    print('你输入的整数是:{}'.format(int(num)))
except: #若不写异常类型,则默认捕获所有异常。
    print('你输入的不完全是数字')

#可多分支捕获不同异常类型,进行相应的异常处理。
try:
    '''被检测的代码块'''
    num = input('请输入数字>>>')
    print('你输入的整数是:{}'.format(int(num)))
except TypeError:
    '''如果捕获到TypeError,就执行这个位置的逻辑'''
    print('捕获到TypeError时的处理逻辑')
except ValueError as e:
    print(e)
else:
    print('被检测代码正常运行,就执行这个位置的逻辑')
finally:
    print('不管被检测代码是否有异常,该逻辑代码块都要执行,通常是进行清理工作')

#可通过所以异常的基类BaseException,捕获所有异常,通过常规错误的基类Exception,捕获常规错误。
try:
    num = input('请输入数字>>>')
    print('你输入的整数是:{}'.format(int(num)))
except BaseException:
    print('你输入的不完全是数字')

断言

除了不可控的异常出现之外,有些代码需要特定的运行条件,那么,我们可以认为抛出异常。python中抛异常的方式有两种,断言,或者raise语句。其中,断言需要判定条件,而raise是直接后接需要抛出的异常类型。二者应用场合在我的理解中略有分别,断言常常使用于根据条件成立来决定抛异常的与否,通常用于为接下来执行的代码正常运行从而进行数据校验。例如,一个变量初始值为空,在程序运行到一半它从网络获取数据,如果没有数据,那么,程序无法执行。就可以使用断言来判定变量是否为空,如果为空,则直接抛异常,并给出告警。当然,raise可以实现同样功能,不过它需要一个if判别。因此,在代码使用上来讲,断言更为简洁,并且它也能被exception捕获。我们首先来看下断言机制。

try:
    num = eval(input('请输入一个结果等于9的表达式:'))
except BaseException:
    print('你输入的表达式不规范')
else:
    """断言关键字使用,后接判定条件,如果条件成立,则无异常。不成立,抛AssertionError异常。<br>用","分割,后接给出的告警信息。告警信息也可以省略"""
    assert num == 9, "脑子是个好东西,我希望你有一个。好好计算!"
    print("你真聪明!")

抛出异常

程序的执行过程中如出现异常事件,可以生成一个异常对象,断言的语句用于已知的条件调试相对简洁。但有些异常时python定义的异常类里面存在的,为了方便快捷,我们可以直接抛出,无需定义异常信息,这时就需要raise来解决了。

raise NameError("name error!")#抛出一个NameError异常,可以给一个打印信息,也可以不给
#常规自定义具体异常信息应该尽量抛Exception类 这里仅做其他类示范。
print("然而并没有错误!") #抛出异常后尝试打印点神马

如上,raise可以直接抛出python自带的异常类,一看就知道哪里出了错误,所以如果不需要条件判定的是自定义异常信息,尽量抛Exception类。这样不至于混淆异常信息。以上代码都立足于功能示范,在实际使用中,一旦抛出异常,程序就会崩溃。所以常规的抛异常大多用于代码调试。如果是为了预防未知信息,抛异常应该出现try--except语句的try下属代码模块,然后用except捕获,再给出相应的解决方案。

自定义异常类

python允许你根据需求定义自己的异常类,但必须继承所异常类的基类BaseException。

class EgonException(BaseException):
    def __init__(self,msg):
        self.msg=msg
    def __str__(self):
        return self.msg

try:
    raise EgonException('类型错误')
except EgonException as e:
    print(e)
原文地址:https://www.cnblogs.com/us-wjz/p/11001032.html