Python实战基础19-异常处理及程序调试

news2024/11/24 14:49:46

1、异常概述

在程序运行过程中,经常会遇到各种各样的错误,这些错误统称为“异常”。

这些异常有的是由于开发者将关键字敲错,这类错误产生的是SyntaxError:invalid syntax(无效语法),这将直接导致程序不能运行。这类异常是显式的,在开发阶段很容易被发现。

还有一类是隐式的,通常和使用者的操作有关。

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

1.1 模拟幼儿园分苹果

【任务描述】

幼儿园每天都要分苹果,老师每次口头计算都比较麻烦,请定义一个模拟分苹果的函数division()。在改函数中,要求输入苹果的数量和小朋友的数量,然后应用除法算式计算分配的结果(不能有小数),输出每人分配的苹果树和剩余的苹果数。

def division():
    '''功能:分苹果'''
    print('\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()

1.2  模拟幼儿园分苹果(除数不为0) 

【任务描述】

在1.1中写出了分苹果的函数,正常情况下可以运行,但是在输入小朋友人数为0的时候程序报错,这是不允许的,希望通过异常捕获的方法,捕捉这个异常。

def division():
    '''功能:分苹果'''
    print('\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个小朋友分!")

运行结果: 

2、异常处理语句

在程序开发时,有些错误并不是每次运行都会出现。例如1.1,只要输入的数据符合程序的要求,程序就可以正常运行,否则将抛出异常并停止运行。

假设在输入苹果的数量时,输入了23.5,那么将抛出如下图所示的异常

这时,就需要在开发程序时对可以出现异常的情况进行处理。 

2.1 try...except语句

语法格式:

try:

        block1

except [exceptionname [as alias]]:

        block2

参数说明:

block1:表示可能出现的错误的代码块

exceptionname [as alias]:可选参数,用于指定要捕获的异常。其中,ExceptName表示要捕获的异常名称,如果在其右侧加上as alias,则表示为当前的异常指定一个别名,通过改别名,可以记录异常的具体内容。

说明:

  • 在使用try...except语句捕获异常时,如果在except后面不指定异常名称,则表示捕获全部异常。
  • block2:表示进行异常处理的代码块。在这里可以输出固定的提示信息,也可以通过别名输出异常的具体内容。
  • 使用try...except语句捕获异常后,当程序出错时,输出错误信息后,程序会继续执行。

从上图能看出,输入了小数,抛出ValueError(传入值的错误)异常。要解决改问题,可以在1.2代码中为try...except语句在添加一个except语句,用于处理抛出ValueError异常的情况。

def division():
    '''功能:分苹果'''
    print('\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:
        print('输入错误',e)

运行结果:

多学两招:

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

try:
    division()
except (ZeroDivisionError,ValueError) as e:
    print("输入错误",e)

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

2.2 try...except...else语句

语法格式:

try:

        # 代码段1

        pass

except name:

        # 代码段2

        pass

else:

        # 代码段3

        pass

就是再原来try...except语句的基础上再添加了一个else子句,用于指定当try语句块中没有发现异常时要执行的语句块。该语句块中的内容当try语句中发现异常时,将不被执行。

例如,对2.1进行修改,实现当division()函数被执行后没有抛出异常时,输出文件”分苹果顺利完成!!”。

def division():
    '''功能:分苹果'''
    print('\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:
        print('输入错误',e)
    else:
        print('分苹果顺利完成!!')

 

2.3 try...except...finally语句

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

语法格式:

try:

        block1

except [exceptionname [as alias]]:

        block2

finally:

        block3

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

说明:

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

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

def division():
    '''功能:分苹果'''
    print('\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:
        print('输入错误',e)
    else:
        print('分苹果顺利完成!!')
    finally:
        print('进行了一次分苹果操作')

运行结果:

 

 

2.4 使用raise语句抛出异常

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

语法格式:

raise [ExceptionName[(reason)]

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

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

2.5 模拟幼儿园分苹果(使用raise抛出异常)

【任务描述】

在1.2中我们写处理分苹果的函数,现在学校要求小朋友至少分到一个苹果,如果每个小朋友没有平均分到一个苹果则抛出错误,并把“苹果太少,不够分!!!打印在屏幕上”。

def division():
    '''功能:分苹果'''
    print("\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, "个,剩下", remain, "个")
if __name__ == "__main__":
    try:
        division()
    except ZeroDivisionError:
        print("\n出错!!!苹果不能够被0个小朋友分")
    except ValueError as e:
        print("出错了",e)

运行结果:

说明:在应用raise抛出异常时,要尽量选择合理的异常对象,而不应该抛出一个与实际内容不相关的异常。 

3、程序调试

在程序开发过程中,免不了会出现一些错误,有语法方面的,也有逻辑方面的。对于语法方面的好检测,因为程序会直接停止,并且给出错误的提示。

对于逻辑错误就不太容易发现了,因为程序可能会一直执行下去,但结果是错误的。

3.1 使用自带的IDLE进行程序调试

多数的集成开发工具都提供了程序调试功能。

例如,我们一直使用的IDLE,也提供了程序调试功能。使用IDLE进行程序调试的基本步骤如下:

(1)打开IDLE(Python Shell),在主菜单上选择“Debug”→“Debugger"菜单项,将打开Debug Control对话框(此时该对话框时空白的),同时Python Shell窗口中将显示”[DEBUG ON]“(表示以及处于调试状态。如下图:

 (2)在Python Shell窗口中,选择”File“ → ”Open“菜单项,打开要调试的文件,这里我打开之前写的模拟幼儿园分苹果.py文件,然后添加需要的断点。 

说明:断点的作用:设置断点后,程序执行到断点时就会暂时中断执行,程序可以随时继续。

添加断点的方法是: 在想要添加断点的行上,单击鼠标右键,在弹出的快捷菜单中选择”Set Breakpoint“菜单项。添加断点的行将以黄色底纹标记,如下图:

说明:如果想要删除已经添加的断点,可以选中已经添加断点的行,然后单击鼠标右键,在弹出的快捷菜单中选中”Clear Breakpoint“菜单项。

 (3)添加所需的断点(添加断点的原则是:程序执行到这个位置时,想要查看某些变量的值,就在这个位置添加一个断点)后,按下快捷键【F5】,执行程序,这时Debug Control对话框中将显示程序的执行信息,选中Globals复选框,将显示全局变量,默认只显示局部变量。此时的Debug Control对话框如下图:

(4)在上图所示的调试工具栏中,提供了5个工具按钮。这里单击“Go”按钮继续执行程序,直到所设置的第一个断点。由于在py文件中,第一个断点之前需要获取用户的输入,所以需要在Python Shell窗口中输入苹果和小朋友的数量。输入后Debug Control窗口的数据将发生变化,如下图:

说明:在调试工具栏中的5个按钮的作用为:Go按钮用于执行跳至断点操作;Step按钮用于进入要执行的函数;Over按钮表示单步执行;Out按钮表示跳出所在的函数;Quit按钮表示结束调试。

(5)继续单击“Go”按钮,将执行到下一个断点,查看变量的变化,直到全部断点都执行完毕。

程序调试完毕后,可以关闭Debug Control窗口,此时在Python Shell窗口将显示“[DEBUG OFF]"(表示已经结束调试)。 

3.2 使用assert语句调试程序

Python提供了assert语句来调试程序。assert的中午意思是断言,它一般用于对程序某个时刻必须满足的条件进行验证。

基本语法:

assert expression [,reason]

参数说明:

expression:条件表达式,如果该表达式的值为真时,什么都不做,如果为假时,则抛出AssertionError异常。

Reason:可选参数,用于对判断条件进行描述为了以后更好地知道哪里出现了问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/609129.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3.二进制高可用安装k8s 1.23集群(生产级)

二进制高可用安装k8s集群(生产级) 本文档适用于kubernetes1.23 节点 Etcd Cluster Etcd是一个数据库,k8s做的一些变更啥的都会存到Etcd中 如果集群比较大建议与master节点分装,单独装Etcd master节点 master分为几个重要的组件 你所有的流量都会经过Kube-APIServer Co…

排序算法——希尔排序图文详解

文章目录 希尔排序基本思想整体插入思想预排序结论 代码实现实现代码直接插入排序与希尔排序的效率比较测试代码&#xff1a; 时间复杂度 希尔排序 注1&#xff1a;本篇是基于对直接插入排序法的拓展&#xff0c;如果对直接插入法不了解&#xff0c;建议先看看直接插入排序 注…

Learning C++ No.27 【布隆过滤器实战】

引言 北京时间&#xff1a;2023/5/31/22:02&#xff0c;昨天的计算机导论考试&#xff0c;三个字&#xff0c;哈哈哈&#xff0c;摆烂&#xff0c;大致题目都是一些基础知识&#xff0c;但是这些基础知识都是非常非常理论的知识&#xff0c;理论的我一点不会&#xff0c;像什么…

【自制C++深度学习框架】表达式层的设计思路

表达式层的设计思路 在深度学习框架中&#xff0c;Expression Layer&#xff08;表达式层&#xff09;是指一个通用的算子&#xff0c;其允许深度学习网络的不同层之间结合和嵌套&#xff0c;从而支持一些更复杂的操作&#xff0c;如分支之间的加减乘除&#xff08;elementAdd…

PyTorch 深度学习 || 专题二:PyTorch 实验框架的搭建

PyTorch 实验框架的搭建 1. PyTorch简介 PyTorch是由Meta AI(Facebook)人工智能研究小组开发的一种基于Lua编写的Torch库的Python实现的深度学习库&#xff0c;目前被广泛应用于学术界和工业界&#xff0c;PyTorch在API的设计上更加简洁、优雅和易懂。 1.1 PyTorch的发展 “…

Numpy---生成数组的方法、从现有数组中生成、生成固定范围的数组

1. 生成数组的方法 np.ones(shape, dtypeNone, orderC) 创建一个所有元素都为1的多维数组 参数说明: shape : 形状&#xff1b; dtypeNone: 元素类型&#xff1b; order &#xff1a; {‘C’&#xff0c;‘F’}&#xff0c;可选&#xff0c;默认值&#xff1a;C 是否在内…

BPMN2.0自动启动模拟流程

思路&#xff1a;BPMN的流程模拟启动&#xff0c;主要是通过生成令牌&#xff0c;并启动令牌模拟 流程模拟的开启需要关键性工具&#xff1a;bpmn-js-token-simulation&#xff0c;需要先行下载 注&#xff1a;BPMN2.0的流程模拟工具版本不同&#xff0c;启动方式也不一样&am…

Kafka某Topic的部分partition无法消费问题

今天同事反馈有个topic出现积压。于是上kfk管理平台查看该topic对应的group。发现6个分区中有2个不消费&#xff0c;另外4个消费也较慢&#xff0c;总体lag在增长。查看服务器日志&#xff0c;日志中有rebalance 12 retry 。。。Exception&#xff0c;之后改消费线程停止。 查…

chatgpt赋能python:Python实现数据匹配的方法

Python实现数据匹配的方法 在数据分析和处理中&#xff0c;经常需要将两组数据进行匹配。Python作为一门强大的编程语言&#xff0c;在数据匹配方面也有着其独特的优势。下面我们将介绍Python实现数据匹配的方法。 数据匹配 数据匹配通常指的是将两组数据根据某些特定的规则…

理解calico容器网络通信方案原理

0. 前言 Calico是k8s中常用的容器解决方案的插件&#xff0c;本文主要介绍BGP模式和IPIP模式是如何解决的&#xff0c;并详细了解其原理&#xff0c;并通过实验加深理解。 1. 介绍Calico Calico是属于纯3层的网络模型&#xff0c;每个容器都通过IP直接通信&#xff0c;中间通…

试验SurfaceFlinger 中Source Crop

在 SurfaceFlinger 中&#xff0c;Source Crop 是用于指定源图像的裁剪区域的一个概念。Source Crop 可以理解为是一个矩形区域&#xff0c;它定义了源图像中要被渲染到目标区域的部分。在 Android 中&#xff0c;Source Crop 通常用于实现屏幕分辨率适应和缩放等功能。 在 Sur…

【Java基础篇】逻辑控制练习题与猜数字游戏

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a;Java.SE&#xff0c;本专栏主要讲解运算符&#xff0c;程序逻辑控制&#xff0c;方法的使用&…

2023_Python全栈工程师入门教程目录

2023_Python全栈工程师入门教程 该路线来自慕课课程,侵权则删,支持正版课程,课程地址为:https://class.imooc.com/sale/python2021 学习路线以三个项目推动,一步步夯实技术水平&#xff0c;打好Python开发基石 目录: 1.0 Python基础入门 2.0 Python语法进阶 3.0 Python数据…

windows系统典型漏洞分析

内存结构 缓冲区溢出漏洞 缓冲区溢出漏洞就是在向缓冲区写入数据时&#xff0c;由于没有做边界检查&#xff0c;导致写入缓冲区的数据超过预先分配的边界&#xff0c;从而使溢出数据覆盖在合法数据上而引起系统异常的一种现象。 ESP、EPB ESP&#xff1a;扩展栈指针&#xff08…

React.memo()、userMemo 、 userCallbank的区别及使用

本文是对以下课程的笔记输出&#xff0c;总结的比较简洁&#xff0c;若大家有不理解的地方&#xff0c;可以通过观看课程进行详细学习&#xff1b; React81_React.memo_哔哩哔哩_bilibili React76_useEffect简介_哔哩哔哩_bilibili React136_useMemo_哔哩哔哩_bilibili Rea…

直播录音时准备一副监听耳机,实现所听即所得,丁一号G800S上手

有些朋友在录视频还有开在线会议的时候&#xff0c;都会遇到一个奇怪的问题&#xff0c;就是自己用麦克风收音的时候&#xff0c;自己的耳机和别人的耳机听到的效果不一样&#xff0c;像是音色、清晰度不好&#xff0c;或者是缺少伴奏以及背景音嘈杂等&#xff0c;这时候我们就…

2023贵工程团体程序设计赛

A这是一道数学题&#xff1f; 道路有两边。 #include<bits/stdc.h> using namespace std; int main(){int n,m;cin>>n>>m;cout<<(n/m1)*2;return 0; } BCPA的团体赛 直接输出 。 #include <bits/stdc.h> using i64 long long; #define IOS…

Docker基本管理与网络以及数据管理

目录 一、Docker简介1、Docker简述2、什么是容器3、容器的优点4、Docker的logo及设计宗旨5、Docker与虚拟机的区别6、Docker的2个重要技术7、Docker三大核心概念 二、Docker的安装及管理1、安装Docker2、配置Docker加速器3、Docker镜像相关基础命令①搜索镜像②拉取镜像③查看镜…

Linux 配置Tomcat环境(二)

Linux 配置Tomcat环境 二、配置Tomcat1、创建一个Tomcat文件夹用于存放Tomcat压缩包2、把Tomcat压缩包传入服务器3、解压并启动Tomcat4、CentOS开放8080端口 二、配置Tomcat 1、创建一个Tomcat文件夹用于存放Tomcat压缩包 输入指令 cd /usr/local 进入到 usr/local 输入指令 …

[LsSDK][tool] ls_syscfg_gui2.0

文章目录 一、简介1.工具的目的2. 更新点下个更新 三、配置文件 一、简介 1.工具的目的 ① 可视化选择IO口功能。 ② 自由配置IO支持的功能。 ③ 适用各类MCU&#xff0c;方便移植和开发。 ④ 功能配置和裁剪&#xff08;选项-syscfg-待完成–需要适配keil语法有些麻烦&#…