第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. koa+mysql+vue+socket.io全栈开发之数据访问篇

    后端搭起大体的框架后,接着涉及到的就是如何将数据持久化的问题,也就是对数据库进行 CURD 操作. 关于数据库方案, mongodb 和 mysql 都使用过,但我选用的是 mysql,原因: 目前为 ...

  2. 前端利用百度开发文档给的web服务接口实现对某个区域周边配套的检索

    最近项目需要实现地图功能,以便于实现对房源周边配套设施的检索.内容如下 其实百度官方有对应的api,但是对于一个网站来说这样的样式难免有些难看 这样的结果显然不能满足当下的需求,所以我决定利用官方给的 ...

  3. DateUtil日期工具类

    目录 (1)需要导入的包 (2)DateUtil类 (1)需要导入的包 主要用于Strings.isNullOrEmpty(date) <!--string处理类--> <depen ...

  4. js 异步转同步

    在项目中有些逻辑或者请求依赖另一个异步请求,大家常用的方法是回调函数.现在有个高大上的解决方案:await async . async 是“异步”的简写,而 await 可以认为是 async wai ...

  5. geoserver发布mysql表数据

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.环境部署 Geoserver中并不自带mysql数据发布功能,需要下 ...

  6. Spark初步 从wordcount开始

    Spark初步-从wordcount开始 spark中自带的example,有一个wordcount例子,我们逐步分析wordcount代码,开始我们的spark之旅. 准备工作 把README.md ...

  7. scrapy爬虫 快速入门

    Scrapy 1. 简介 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络 ...

  8. 吴恩达机器学习笔记58-协同过滤算法(Collaborative Filtering Algorithm)

    在之前的基于内容的推荐系统中,对于每一部电影,我们都掌握了可用的特征,使用这些特征训练出了每一个用户的参数.相反地,如果我们拥有用户的参数,我们可以学习得出电影的特征. 但是如果我们既没有用户的参数, ...

  9. 查找第三方银行官方app下载链接探索过程

    需求:最近有个需求,点击按钮,弹出一个所需银行选项的非全屏弹出层,再点击某银行选项,随即跳转到该银行的app下载界面,如下图所示           注:这里只是引用相关银行的链接,不需要做什么逻辑处 ...

  10. 微软跨平台ORM框架之EFCore — 约定与属性映射

    EFCore中的约定简单来说就是规则,CodeFirst基于模型的约定来映射表结构.除此之外还有Fluent API.Data Annotations(数据注释) 可以帮助我们进一步配置模型. 按照这 ...