第16天:Python 错误和异常


                                                                                                                                                                                                                                                       

图片

做为 Python 初学者,在刚学习 Python 编程时,常常会看到一些报错信息,这些报错信息就是咱们接下来要讲的错误和异常。python

咱们在执行程序语句的时候,常常会看到命令行输出报错信息,例如:编程

>>> while True print('Hello world')  File "<stdin>", line 1, in ?    while True print('Hello world')                   ^SyntaxError: invalid syntax

这种报错信息会阻止程序正常运行,也就是咱们要介绍的错误和异常。数据结构

错误

咱们说的错误指的是Python的语法错误,例如:app

>>> if 1=1: print('always')  File "<stdin>", line 1    if 1=1: print('always')        ^SyntaxError: invalid syntax

上面例子中,在判断相等的时候应该用''==',而不是用'=',执行的时候,语法解析器检查到有错误,程序语句终止执行,并将错误的地方用上箭头指出来。ide

语法错误很好解决,根据命令行提示的错误位置,检查语法,改正便可。函数

异常

在Python中,即便你的代码没有语法错误,也不能保证程序按照你的想法运行完毕,由于在程序执行过程当中也会有错误。程序运行期间检测到的错误被称为异常,例如:学习

>>> '1' + 2Traceback (most recent call last):  File "<stdin>", line 1, in ?TypeError: Can't convert 'int' object to str implicitly

大多数的异常都不会被程序处理,都以错误信息的形式显示出来,如上例所示,提示信息告诉咱们int类型不能和str类型相加。spa

错误提示信息会告诉咱们异常发生的上下文,并以调用栈的形式显示具体信息,提示信息的最后一行开头会显示错误类型名称,上例中,错误类型为'TypeError',表示类型异常。命令行

什么是异常

异常是一个事件,该事件会在程序执行过程当中发生,从而影响程序的正常执行。当 Python遇到没法处理的程序时,就会引起一个异常。在 Python 中,异常是一个对象,用于表示一个错误,当 Python脚本发生异常时咱们须要捕获和处理它,不然程序会终止执行。3d

处理异常

Python 提供了 try/except语句用来捕获和处理异常。try 语句用来检测语句块中是否有错误,except 语句则用来捕获 try 语句中的异常,并进行处理,附加的 else 能够在 try 语句没有异常时执行。

语法

下面以最简单的 try...except...else 为例:

try:    statement(s)            # 要检测的语句块except exception:    deal_exception_code # 若是在 try 部份引起了 'exception' 异常except exception2, e:    deal_exception2_code # 若是引起了 'exception2' 异常else:    no_exception_happend_code #若是没有异常发生

try 语句的执行逻辑以下:

  • 首先,执行 try 子句 (try 和 except 关键字之间的(多行)语句)。

  • 若是没有异常发生,则跳过 except 子句 并完成 try 语句的执行。

  • 若是在执行try 子句时发生了异常,则跳过该子句中剩下的部分。而后,若是异常的类型和 except 关键字后面的异常匹配,则执行 except 子句,而后继续执行 try 语句以后的代码。

  • 若是发生的异常和 except 子句中指定的异常不匹配,则将其传递到外部的 try 语句中;若是没有找处处理程序,则它是一个 未处理异常,执行将中止并显示错误消息。

  • 若是 try 语句执行时没有发生异常,那么将执行 else 语句后的语句(若是有 else 的话),而后控制流经过整个 try 语句。

基类

若是发生的异常和 except 子句中的类是同一个类或者是它的基类,则异常和 except 子句中的类是兼容的(但反过来则不成立 --- 列出派生类的 except 子句与基类兼容)。

实例
class BException(Exception):  #继承Exception基类    pass
class CException(BException):  #继承BException基类    pass
class DException(CException):  #继承CException基类    pass
for cls in [BException, CException, DException]:    try:        raise cls()  #抛出异常    except DException:        print("D")    except CException:        print("C")    except BException:        print("B")
#输出BCD

请注意若是  except 子句被颠倒(把 except BException 放到第一个),它将打印 B,B,B ---  由于DException类继承CException类,CException类继承BException类,将 except BException  放到第一个能够匹配这三个异常,后面的 except 就不会执行。

不带异常类型的 except

Python能够在全部 except 的最后加上 except 子句,这个子句能够省略异常名,以用做通配符。它能够捕获前面任何 except (若是有的话)没有捕获的全部异常。

try:    statement(s)            # 要检测的语句块except exception:    deal_exception_code # 若是在 try 部份引起了 'exception' 异常except :    deal_all_other_exception2_code # 处理所有其它异常else:    no_exception_happend_code #若是没有异常发生
实例
try:    raise BException()  #抛出异常except DException:    print("D")except:    print("处理所有其它异常") #处理所有其它异常
#输出处理所有其它异常

except 语句捕获多种异常类型

一个 try 语句可能有多个 except 子句,以指定不一样异常的处理程序,最多会执行一个处理程序。处理程序只处理相应的 try 子句中发生的异常,而不处理同一 try 语句内其余处理程序中的异常。一个 except 子句能够将多个异常命名为带括号的元组。

try:    statement(s)            # 要检测的语句块except exception:    deal_exception_code # 若是在 try 部份引起了 'exception' 异常except (Exception1[, Exception2[,...ExceptionN]]]) :    deal_all_other_exception2_code # 处理多个异常else:    no_exception_happend_code #若是没有异常发生
实例
try:    raise BException()  #抛出异常except (BException, DException):    print("D")except:    print("处理所有其它异常") #处理所有其它异常else:    print("没有异常发生") #没有异常发生
#输出D

try - finally 语句

finally 语句用于不管是否发生异常都将执行最后的代码。

try:    # <语句>finally:    # <语句>    #退出try时总会执行
实例
try:    raise BException()  #抛出异常except (BException, DException):    print("D")except:    print("处理所有其它异常") #处理所有其它异常else:    print("没有异常发生") #没有异常发生finally:    print("大家绕不过我,必须执行") #必须执行的代码 #输出D大家绕不过我,必须执行

这里注意 finally 和 else 的区别,finally 是不管是否有异常都会执行,而 else 语句只有没有异常时才会执行。也就是说若是没有异常,那么 finally 和 else 都会执行。

异常的参数

except 子句能够在异常名称后面指定一个变量。这个变量和一个异常实例绑定,它的参数是一个元组,一般包含错误字符串,错误数字,错误位置,存储在 .args 中。为了方便起见,异常实例定义了__str__() ,所以能够直接打印参数而无需引用 .args。

try:    # 正常的操做 ......except ExceptionType as inst:    # 能够在这输出 inst 的值.....
实例
try:    x = 1 / 0  # 除数为0except ZeroDivisionError as err: #为异常指定变量err    print("Exception")    print(err.args) #打印异常的参数元组    print(err) #打印参数,由于定义了__str__()
#输出Exception('division by zero',)division by zero

触发异常

Python 提供了 raise 语句用于手动引起一个异常。

语法
raise [Exception [, args [, traceback]]]
参数说明
Exception:异常的类型,例如 ZeroDivisionErrorargs:异常参数值,可选,默认值 "None"traceback:可选,用于设置是否跟踪异常对象

异常参数值能够是一个字符串,类或对象

实例
def diyException(level):    if level > 0:        raise Exception("raise exception", level)  #主动抛出一个异常,而且带有参数        print('我是不会执行的') #这行代码不会执行
try:   diyException(2)  #执行异常方法except Exception as err: #捕获异常    print(err) #打印异常参数#输出('raise exception', 2)

为了可以捕获异常,"except"语句必须有用相同的异常来抛出类对象或者字符串。若是要捕获上面代码抛出的异常,except 语句应该以下所示:

#定义函数def diyException(level):    if level > 0:        raise Exception("error level", level)  #主动抛出一个异常,而且带有参数        print('我是不会执行的') #这行代码不会执行
try:   diyException(2)  #执行异常方法except 'error level' as err: #捕获异常    print(err) #打印异常参数
#输出Traceback (most recent call last):  File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 51, in <module>    diyException(2)  #执行异常方法  File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 47, in diyException    raise Exception("error level", level)  #主动抛出一个异常,而且带有参数Exception: ('error level', 2)

固然,咱们也能够经过 traceback 来捕获异常:

import traceback
#定义函数def diyException(level):    if level > 0:        raise Exception("error level", level)  #主动抛出一个异常,而且带有参数        print('我是不会执行的') #这行代码不会执行
try:   diyException(2)  #执行异常方法except Exception: #捕获异常    traceback.print_exc()#输出Traceback (most recent call last):  File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 51, in <module>    diyException(2)  #执行异常方法  File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 47, in diyException    raise Exception("error level", level)  #主动抛出一个异常,而且带有参数Exception: ('error level', 2)

用户自定义异常

除了使用 Python 内置的异常,咱们还能够建立本身的异常类型。建立本身的异常很是简单,只须要建立一个类,并继承 Exception 类或其子类。

下面的代码建立了一个异常 DiyError 继承自 Python 内置的 RuntimeError,用于在异常触发时输出更多的信息。

#自定义异常class DiyError(RuntimeError):    def __init__(self, arg):        self.args = arg
try:    raise DiyError("my diy exception") #触发异常except DiyError as e:    print(e)

定义好了以后,咱们就能够在 except 语句后使用 DiyError 异常,变量 e 是用于建立 DiyError 类的实例。咱们也能够经过 raise 语句手动触发这个异常。

预约义的清理行为

一些对象定义了标准的清理行为,不管系统是否成功的使用了它,一旦不须要它了,那么这个标准的清理行为就会执行。

for line in open("myfile.txt"):    print(line, end="")

上面这个例子尝试打开一个文件,而后把内容打印出来。可是有一个问题:当执行完毕后,程序没有关闭文件流,文件会保持打开状态。

关键词 with 语句就能够保证诸如文件之类的对象在使用完以后必定会正确的执行他的清理方法。

with open("myfile.txt") as f:    for line in f:        print(line, end="")

以上这段代码执行完毕后,就算在处理过程当中出问题了,文件 f 老是会关闭。这里面的原理就是使用了 finally 机制,有兴趣的能够去深刻了解一下。

总结

本节给你们介绍了 Python 错误和异常的使用,掌握了错误和异常的处理,能够极大地提升程序的健壮性,为程序的持续完整运行提供了保障。

系列文章


  第11天:Python 字典

第10天:Python 类与对象

第9天:Python Tupple

第8天:Python List

第7天:Python 数据结构--序列

第6天:Python 模块和

第5天:Python 函数

第4天:Python 流程控制

第3天:Python 变量与数据类型

第2天:Python 基础语法

第1天:Python 环境搭建

相关文章
相关标签/搜索