写给Python社群的第8课:Python异常,你必须掌握的技术点

66 阅读6分钟

⛳️ 异常是什么

任何程序都会出错,任何程序员都会写错代码,程序员编写程序一直处于编写,调试的循环中,程序异常也叫做程序BUG,一般情况是代码语法报错,逻辑错误,或者运行环境错误,正式学习异常前还需要提前掌握一句真理。

异常永远无法避免,我们要做的是尽量减少异常。

由于异常无法避免,所以需要区分一下异常级别。

最简单的异常 语法错误是Python编码过程中最简单的异常,也就是代码语法出错,一般编辑器,即开发工具就会提示出异常信息和异常位置,直接修改即可。该类错误是新手在初学阶段常犯的错误之一。

隐性错误 该类异常不好排查,一般是代码有逻辑错误或者缺陷,只有当程序满足某些特定条件的时候,才会触发,例如当程序要求用户输入数字,而我们又没有提前验证,当用户输入非数字字符时,就会报错。

隐性错误是未来我们检查程序健壮性的主要切入点,因其不容易被发现,且编码过程中编译正常,运行正常,甚至有些错误出现后程序都能正常运行,如果让这样的错误在程序中,并且积累了一段时间,将造成无法修复的重大事故。

高级错误 这类错误一般属于不确定性错误,例如打开文件的时候,发现文件被占用(在 windows 上删除 word 文档,或者改名时,就会出现该异常,提示文件被占用),还有程序在传输网络数据的时候,网络突然被中断,手机或者电脑突然死机,这些都属于高级错误,而且充满不确定性,在实战中我们要尽可能的想到这些错误,并提前做好异常处理,这才是本篇博客核心要探究的内容。

⛳️ 异常捕获

我们先从捕获Python程序中异常的通用方法开始学习,即当Python程序出错时,通过何种语法将其捕获到。

基本异常捕获语句 首先看一下异常捕获的语法格式。

try:
	待捕获异常的语句
except:
	捕获异常之后的操作

其中关键字 try 表示异常语句的开始,待捕获异常的语句 是可能出现异常的位置,关键字 except 用来捕获异常,并输出错误信息,接下来编写一段异常捕获代码,用于捕获当除数为0时,出现的异常信息

chushu = 0
try:
    ret = 10/chushu
    print(ret)
except:
    print("除数不能为0")

上述代码中的 chushu 可以切换为0或者其它值,然后查看对应的输出信息。

除了 tryexcept 两个关键字外,还有 finally 也是异常语句中出现频率较高的关键字,其表示无论程序是否出现异常,都需要执行的代码

try:
	待捕获异常的语句
except:
	捕获异常之后的操作语句
finally:
	无论是否出现异常,这里的代码都要执行

修改除数不为零的程序,示例如下:

chushu = 0
try:
    ret = 10/chushu
    print(ret)
except:
    print("除数不能为0")
finally:
    print("我一直需要执行")

经过测试也可以得到相应的结论,即 finally 语句无论程序是否出现异常,都会执行。

这里再扩展一个知识点,finally 语句具备强制性,即当程序被退出时,也要执行完毕 finally 中的代码,才会退出。 下述代码需要用到 sys 对象的退出方法 exit()

import sys
chushu = 1
try:
    ret = 10/0
    print(ret)
    
except:
    print("除数不能为0")
    sys.exit()
finally:
    print("我一直需要执行")

print("我无法被执行到了")

输出信息比较多,这里截图给大家展示,可以看到即使程序出错时被强制结束,finally 也继续执行。 在这里插入图片描述

⛳️ 异常类型

本小节时本篇博客的重点,就是异常类型,关键点为 except 语句,其后可以捕获特定异常信息,在前文图片中,如果你细心观察,会发现一个单词 ZeroDivisionError ,翻译一下表示除数不能为零,这就是错误类型,常见的错误类型如下所示。

  • ValueError:值错误;
  • IndexError:索引错误,例如在列表读取的时候,经常碰到该错误类型;
  • SyntaError:语法错误,最常见的错误,编译器无法执行的代码,都会展示该错误;
  • NameError:对象名不存在,例如直接运行该代码 print(name),就会出现该错误类型的提示;
  • KeyError:操作字典时,Key 不存在;
  • TypeError:数据类型错误;
  • ModuleNoFoundError:导入模块错误;
  • AttributeError:属性错误。

这些都属于常见错误,Python 内置的错误类型远远不止这些,如果希望学习更多,可以直接搜索 Python 异常类型,然后学习更多资料,使用 except 捕获特定异常的操作如下所示。

try:
    print(name)
except NameError as n:
    print(n)

重点查看 except NameError as n:,其 except 关键字后跟的就是异常类型,as 是重命名的含义,所以 n 就表示捕获到的 NameError 对象。 输出 n,也就输出了错误信息。

except 还可以支持多次捕获,代码如下。

try:
    print(name)
except NameError as n:
    print("NameError")
    print(n)
except Exception as n:
    print("Exception")
    print(n)

这里执行顺序是:优先进入捕获到异常类型的语句中,执行操作,所以得到的输出如下所示。

NameError
name 'name' is not defined

前文的代码中,还出现了一个未罗列的异常类型,即 Exception,该类是所有异常的类的基类(父类),所以当你不能百分百明确异常类型的时候,可以含糊的使用 Exception

⛳️ raise 抛出异常

实际工作中碰到的项目,有时候需要手动抛出异常,这就需要用到 raise 关键字了,其语法格式如下。

raise '异常信息'

使用的时候可以携带异常信息,也可以忽略,代码如下。

def show_exception():
    raise 
    
def show():
    raise '抛出异常'
show()

直接运行代码,会出现类型错误,即 TypeError: exceptions must derive from BaseException,该异常表示 raise 关键字抛出的异常,未指定异常类型,进行一下简单修改,即可完美运行,代码如下。

def show():
    raise Exception('抛出异常')
show()

本文正在参加「金石计划 . 瓜分6万现金大奖」