第9章 异常处理及程序调试

9.1 异常概述

在程序运行过程中,经常会遇到各种各样的错误,这些错误统称为“异常”。这些异常有的是由于开发者将关键字敲错导致的,这类错误多数产生的是SyntaxError:invalid syntax(无效的语法),这将直接导致程序不能运行。这类异常是显式的,在开发阶段很容易被发现。还有一类是隐式的,通常和使用者的操作有关。

实例01:模拟幼儿园分苹果

def division():
'''功能:分苹果'''
print("\n=====================分苹果======================\n")
apple = int(input("请输入苹果的个数:")) # 输入苹果的数量
children = int(input("请输入来了几个小朋友:"))
result = apple//children # 计算每人分几个苹果
remain = apple-result*children # 计算余下几个苹果
if remain>0:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个,剩下",remain,"个。")
else:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个。")
if __name__ == '__main__':
division() # 调用分苹果的函数

运行程序,当输入苹果和小朋友的数量都是10时:

请输入苹果的个数:10
请输入来了几个小朋友:10
10 个苹果,平均分给 10 个小朋友,每人分 1 个。

如果在输入数量时,不小心把小朋友的人数输成了0:

产生了ZeroDivisionError(除数为0错误)的根源在于算术表达式“10/0”中,0作为除数出现,所以正在执行的程序中被中断(第6行以后,包括第6行的代码都不会被执行)。

Python中还有很多异常。

Python中常见的异常
异常 描述
NameError 尝试访问一个没有声明的变量引发的错误
IndexError 索引超出序列范围引发的错误
IndentationError 缩进错误
ValueError 传入错误
KeyError 请求一个不存在的字典关键字引发的错误
IOError 输入输出错误(如要读取的文件不存在)
ImportError 当import语句无法找到模块或from 无法在模块中找到相应的名称时引发的错误
AttributeError 尝试访问未知的对象属性引发的错误
TypeError 类型不合适引发的错误
MemoryError 内存不足
ZeroDivisionError 除数为0 引发的错误

9.2 异常处理语句

在程序开发时,有些错误并不是每次运行都会出现。

下面将详细介绍Python中提供的异常处理语句。

9.2.1 try...eccept

在Python中,提供了try...except语句捕获并处理异常。在使用时,把可能产生异常的代码放在try 语句块中,把处理结果放在except 语句块中,这样,当try 语句块中的代码出现错误时,就会执行except语句块中的代码,如果try 语句块中的代码没有错误,那么except 语句块将不会执行。具体的语法格式如下:

try:
block1
except [ExceptionName [as alias]]:
block2

参数说明:

  • block1:表示可能出现错误的代码块。
  • ExceptionName [as alias]:可选参数,用于指定要捕获的异常。其中,ExceptionName表示要捕获的异常名称,如果在其右侧加上as alias,则表示为当前的异常指定一个别名,通过该别名,可以记录异常的具体内容。

说明:在使用try...except语句捕获异常时,如果在except后面不指定异常名称,则表示捕获全部异常。

  • block2:表示进行异常处理的代码块。在这里可以输出固定的提示信息,也可以通过别名输出异常的具体内容。

说明:使用try...except语句捕获异常后,当程序出错时,输出错误信息后,程序会继续执行。

实例02:模拟幼儿园分苹果(除数不能为0)

对“if __name__ =='__main__':”语句下面的代码进行修改,应用try...except语句捕获执行division()函数可能抛出的ZeroDivisionError(除数为零)异常,修改后的代码如下:

def division():
'''功能:分苹果'''
print("\n=====================分苹果======================\n")
apple = int(input("请输入苹果的个数:")) # 输入苹果的数量
children = int(input("请输入来了几个小朋友:"))
result = apple//children # 计算每人分几个苹果
remain = apple-result*children # 计算余下几个苹果
if remain>0:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个,剩下",remain,"个。")
else:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个。")
if __name__ == '__main__':
try: # 捕获异常
division() # 调用分苹果的函数
except ZeroDivisionError: # 处理异常
print("\n出错了 ~_~ ——苹果不能被0个小朋友分!")

执行以上的代码,输入苹果的数量为10,小朋友的人数为0时,将不再抛出异常:

目前,我们只处理了除数为0的情况,如果将苹果和小朋友的数量输入成小数或者不是数字会是什么结果呢?

可以看出,程序中要求输入整数,而实际输入的是小数,则抛出ValueError(传入的值错误)异常。要解决该问题,可以在实例02的代码中,为try...except语句再添加一个except语句,用于处理抛出ValueError异常的情况。修改后的代码如下:

def division():
'''功能:分苹果'''
print("\n=====================分苹果======================\n")
apple = int(input("请输入苹果的个数:")) # 输入苹果的数量
children = int(input("请输入来了几个小朋友:"))
result = apple//children # 计算每人分几个苹果
remain = apple-result*children # 计算余下几个苹果
if remain>0:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个,剩下",remain,"个。")
else:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个。")
if __name__ == '__main__':
try: # 捕获异常
division() # 调用分苹果的函数
except ZeroDivisionError: # 处理异常
print("\n出错了 ~_~ ——苹果不能被0个小朋友分!")
except ValueError as e: # 处理ValueError异常
print("输入错误:",e) # 输出错误原因

再次运行程序:

多学两招:

在捕获异常时,如果需要同时处理多个异常也可以采用下面的代码实现:

try:                                                                 # 捕获异常
division() # 调用分苹果的函数
except (ZeroDivisionError,ValueError) as e: # 处理异常
print("输入错误:",e) # 输出错误原因

即在except语句后面使用一对小括号将可能出现的异常名称括起来,多个异常名称之间使用逗号分隔。如果想要显示具体的出错原因,那么再加上as指定一个别名。

9.2.2 try...except...else 语句

在Python中国,还有另一种异常处理结构,它是try...except...else语句,也就是在原来try...except语句的基础上再添加一个else子句,用于指定当try语句块中没有发现异常时要执行的语句块。该语句块中的内容当try语句中发现异常,将不被执行。例如,实例02进行修改,实现当division()函数被执行后没有抛出异常时,输出文字“分苹果顺利完成...”。修改后的代码如下:

def division():
'''功能:分苹果'''
print("\n=====================分苹果======================\n")
apple = int(input("请输入苹果的个数:")) # 输入苹果的数量
children = int(input("请输入来了几个小朋友:"))
result = apple//children # 计算每人分几个苹果
remain = apple-result*children # 计算余下几个苹果
if remain>0:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个,剩下",remain,"个。")
else:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个。")
if __name__ == '__main__':
try: # 捕获异常
division() # 调用分苹果的函数
except ZeroDivisionError : # 处理异常
print("\n出错了 ~_~ ——苹果不能被0个小朋友分!")
except ValueError as e: # 处理ValueError异常
print("输入错误:",e) # 输出错误原因
else: # 没有抛出异常时执行
print("分苹果顺利完成...")

执行以上代码:

9.2.3 try...except...finally 语句

完整的异常处理语句应该包含finally 代码块,通常情况下,无论程序中有无异常产生,finally 代码块中的代码都会被执行,其语法格式如下:

try:
block1
except [ExceptionName [as alias]]:
block2
fianlly:
block3

对于try...except...finally 语句的理解并不复杂,它只是比try...except 语句多了一个finally 语句,如果程序中有一些在任何情形中都必须执行的代码,那么就可以将它们放在finally 代码块中。

说明:使用except 子句是为了允许处理异常。无论是否引起了异常,使用finally 子句都是可以执行清理代码。如果分配了有限的资源(如打开文件),则应将释放这些资源的代码放置在finally 代码块中。

例如,在对实例02进行修改,实现当division() 函数在执行时无论是否抛出异常,都输出文字“进行了一次分苹果操作”。修改后的代码如下:

def division():
'''功能:分苹果'''
print("\n=====================分苹果======================\n")
apple = int(input("请输入苹果的个数:")) # 输入苹果的数量
children = int(input("请输入来了几个小朋友:"))
result = apple//children # 计算每人分几个苹果
remain = apple-result*children # 计算余下几个苹果
if remain>0:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个,剩下",remain,"个。")
else:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个。")
if __name__ == '__main__':
try: # 捕获异常
division() # 调用分苹果的函数
except ZeroDivisionError : # 处理异常
print("\n出错了 ~_~ ——苹果不能被0个小朋友分!")
except ValueError as e: # 处理ValueError异常
print("输入错误:",e) # 输出错误原因
else: # 没有抛出异常时执行
print("分苹果顺利完成...")
finally: # 无论是否抛出异常都执行
print("进行了一次分苹果操作。")

执行程序:

至此,已经介绍了异常处理语句的try....except、try...except...else 和 try...except...finally 等形式。

异常处理语句的不同子句的执行关系

9.2.4 使用raise 语句抛出异常

如果某个函数或方法可能会产生异常,但不想在当前函数或方法中处理这个异常,则可以使用raise 语句在函数或方法中抛出异常。raise 语句的语法格式如下:

raise [ExceptionName[(reason)]]

其中,ExceptionName[(reason)]为可选参数,用于指定抛出的异常名称以及异常信息的相关描述。如果省略,就会把当前的错误原样抛出。

说明:ExceptionName[(reason)]参数中的“(reason)”也可以省略,如果省略,则在抛出异常时,不附带任何描述信息。

例如,修改实例02,加入限制苹果数量必须大于或等于小朋友的数量,从而保证每个小朋友都能至少分到一个苹果。

实例03:模拟幼儿园分苹果(每个人至少分到一个苹果)

在第5行代码“children = int(input("请输入来了几个小朋友:"))”的下方添加一个if 语句,实现当苹果的数量小于小朋友的数量时,应用raise 语句抛出一个ValueError 异常,接下来再在最后一行语句的下方添加except 语句处理ValueError 异常。

def division():
'''功能:分苹果'''
print("\n=====================分苹果======================\n")
apple = int(input("请输入苹果的个数:")) # 输入苹果的数量
children = int(input("请输入来了几个小朋友:"))
if apple < children:
raise ValueError("苹果太少了,不够分...")
result = apple//children # 计算每人分几个苹果
remain = apple - result*children # 计算余下几个苹果
if remain>0:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个,剩下",remain,"个。")
else:
print(apple,"个苹果,平均分给",children,"个小朋友,每人分",result,"个。")
if __name__ == '__main__':
try: # 捕获异常
division() # 调用分苹果的函数
except ZeroDivisionError : # 处理ZeroDivisionError异常
print("\n出错了 ~_~ ——苹果不能被0个小朋友分!")
except ValueError as e: # ValueError
print("\n出错了~_~ ——",e)

执行程序:

说明:在应用raise 抛出异常时,要尽量选择合理的异常对象,而不应该抛出一个与实际内容不相关的异常。流入,在实例03中,想要处理的是一个和值有关的异常,这时就不应该抛出一个IndentationError异常。

9.3 程序调试

零基础学Python--------第9章 异常处理及程序调试的更多相关文章

  1. [零基础学python]为什么要开设本栏目

    这个栏目的名称叫做"零基础学Python". 如今网上已经有不少学习python的课程.当中也不乏精品.按理说,不缺少我这个基础类型的课程了.可是,我注意到一个问题.无论是课程还是 ...

  2. 零基础学python》(第二版)

    ---恢复内容开始--- 零基础学python>(第二版) python学习手册 可以离线下载,  .chn格式, 插入小幽默笑话,在学习累的时候看看笑话 放松一下 欢迎下载转载,请注明出处,谢 ...

  3. 零基础学python,python视频教程

    零基础学python,python视频教程 这是我收集到的互联网上的视频资源,所有内容均来自互联网.仅供学习使用. 目前我在也在学习过程中,会把学习过程中遇到问题以及解决问题的方式,总结到我的公众号[ ...

  4. 小甲鱼零基础学python第25讲课后习题动手练习--通讯录

    小甲鱼零基础学python第25讲课后习题动手练习---通讯录 **************************通讯录要求******************************* 输入指令: ...

  5. Python学习课程零基础学Python

    python学习课程,零基础Python初学者应该怎么去学习Python语言编程?python学习路线这里了解一下吧.想python学习课程?学习路线网免费下载海量python教程,上班族也能在家自学 ...

  6. 零基础学python之构建web应用(入门级)

    构建一个web应用 前面的学习回顾: IDLE是Python内置的IDE,用来试验和执行Python代码,可以是单语句代码段,也可以是文本编辑器中的多语句程序. 四个内置数据结构:列表.字典.集合和元 ...

  7. 零基础学Python不迷茫——基本学习路线及教程!

    什么是Python? 在过去的2018年里,Python成功的证明了它自己有多火,它那“简洁”与明了的语言成功的吸引了大批程序员与大数据应用这的注意,的确,它的实用性的确是配的上它的热度.   Pyt ...

  8. 零基础学Python 3之环境准备

    一. 配置python 3 环境 1. Python 3 下载 64位 https://www.python.org/ftp/python/3.4.2/python-3.4.2.amd64.msi 3 ...

  9. 零基础学python之函数与模块(附详细的代码和安装发布文件过程)

    代码重用——函数与模块 摘要:构建函数,创建模块,安装发布文件,安装pytest和PEP 8插件,确认PEP8兼容性以及纠错 重用代码是构建一个可维护系统的关键. 代码组是Python中对块的叫法. ...

随机推荐

  1. IE不兼容ES6箭头函数的解决方法(在浏览器中使用)

    polyfill.js下载方法: npm install babel-polyfill --save 页面中引用"polyfill.js" 和 "browser.min. ...

  2. 树莓派3b+_32位linux系统arm架构安装JDK

    如图我的Raspbian系统如下图版本信息: 可以看到是armv7l,我查了一下是32位的arm架构,即下载第一个就好了 然后用SSH Secure Shell远程上去把压缩包或者解压后的文件传过去 ...

  3. 为自己搭建一个分布式 IM 系统二【从查找算法聊起】

    前言 最近这段时间确实有点忙,这篇的目录还是在飞机上敲出来了的. 言归正传,上周更新了 cim 第一版:没想到反响热烈,最高时上了 GitHub Trending Java 版块的首位,一天收到了 3 ...

  4. maven构建失败。

    maven项目编译报“Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1” 解决方案:setting.x ...

  5. 【推荐】 HyperLedger Fabric环境搭建、测试及注意事项 [详尽指导] [亲测有效]

    系统:Ubuntu16.04 LTS 一.环境准备 1.1 Ubuntu下安装 crul sudo apt install curl curl是利用URL语法在命令行方式下工作的开源文件传输工具.它被 ...

  6. FreeSql.DbContext 第二个版本介绍

    FreeSql.DbContext 实现类似 EFCore 使用方法,跟踪对象状态,最终通过 SaveChanges 方法提交事务. 目前是第二个初版,已实现状态跟踪保存(导航属性的跟踪暂时不支持). ...

  7. LDA && NCA: 降维与度量学习

    已迁移到我新博客,阅读体验更佳LDA && NCA: 降维与度量学习 代码实现放在我的github上:click me 一.Linear Discriminant Analysis(L ...

  8. spring源码 — 五、事务

    spring提供了可配置.易扩展的事务处理框架,本文主要从一下几个方面说明spring事务的原理 基本概念 事务配置解析 事务处理过程 基本概念 事务隔离级别 在同时进行多个事务的时候,可能会出现脏读 ...

  9. Oracle 连接查询

    1.什么是连接查询?(B) 很多时候我们需要查询的数据并不是来源于同一张表,而是来源于多张表,而这种一个查询需要对多张表进行操作,就成为连接查询. 2.如何进行表的连接查询? 连接查询有两种方式:SQ ...

  10. 16 , CSS 边框与边界

    1.CSS 中边框的使用 2.CSS 中边界的使用 16.1 CSS 中边框的使用 属性名称 属性值 说明 border-color 十六进制 可依序设置上,右,下,左线颜色 英文名称 border- ...