15.Python 异常处理和程序调试

news2024/12/29 9:08:56

1. 异常处理

异常就是在程序执行过程中发生的超出预期的事件。一般情况下,当程序无法正常执行时,都会抛出异常。

  • 在开发过程中,由于疏忽或考虑不周,出现的设计错误。因此,在后期程序调试中应该根据错误信息,找到出错位置,并对错误代码进行分析和排错。
  • 难以避免的运行问题,如读写权限不一致、网络异常、文件不存在、内存溢出、数据类型不一致等。针对这类异常,在设计时可以主动捕获异常,防止程序意外终止。
  • 主动抛出异常。在程序设计中,可以根据设计需要主动抛出异常,引导程序按照预先设计的逻辑运行,防止用户不恰当地操作。

当发生异常时,一般应该捕获异常,并妥善处理。如果异常未被处理,程序将终止运行,因此为程序添加异常处理,能使程序更健壮。

异常也是一种类型,所有的异常实例都继承自BaseException基类。使用Exception可以捕获所有类型的异常。

使用try…except语句可以捕获和处理异常,语句格式如下:

try:   # 捕获异常
    <执行语句>
except [异常类型[ as 别名]]: # 处理异常
    <处理语句>

把目标代码放在try语句中,在except关键字后面设置可选的异常类型。如果省略异常类型,则表示捕获全部异常类型。如果类型的名称比较长,可以使用as关键字设置别名,方便在异常处理中引用。如果不需要处理异常,可以在except代码块中使用pass语句忽略。

try:
    '1' + 0 # 错误运算
except: # 捕获所有的异常
    print('发生错误') # 提示错误信息

try:
    f = open('test.txt','r') # 打开不存在的文件
except IOError as e:  # 捕获IOError类型异常
    print('错误编号:%s,错误信息:%s'%(e.errno,e.strerror)) #显示错误信息

try:
    f = open('test.txt','r') # 打开不存在的文件
except Exception as e:  # 捕获IOError类型异常
    print('错误编号:%s,错误信息:%s'%(e.errno,e.strerror)) #显示错误信息

使用except语句可以同时处理多个异常,语法格式如下:

# 多个异常类型以元组形式进行设置,当try代码发生其中一个,都被except处理。
try: # 捕获异常
    <执行语句>
except ([Exception1[,Exception2,...,ExceptionN]]) [ as 别名]: # 处理异常
    <处理语句>

# 多个异常类型按优先顺序分别进行处理
try: # 捕获异常
    <执行语句>
except ([Exception1[,Exception2]]) [ as 别名]:
    <处理语句1>
...
except [Exception]:
    <处理语句N>

# 样例
li = [] # 定义空列表
try:
    print(c) # 发生NameError异常
    print(3/0) # 发生ZeroDivisionError异常
    li[2] # 发生IndexError异常
    a = 123 + 'hello world'  # 发生TypeError异常
except NameError as e:
    print('出现NameError异常!',e)
except ZeroDivisionError as e:
    print('出现ZeroDivisionError异常!',e)
except IndexError as e:
    print('出现IndexError异常!',e)
except TypeError as e:
    print('出现TypeError异常!',e)
except Exception as e:
    print('出现其它异常!',e)

try代码块中可以嵌套使用try…except结构,设计多层嵌套的异常处理结构,异常对象可以从内向外逐层向上传递。

try:
    try:
        try:
            f = open('test.txt','r') # 打开并不存在的文件
        except NameError as e: # 捕获未声明的变量异常
            print('NameError')
    except IndexError as e: # 捕获索引超出异常
        print('IndexError')
except IOError as e: # 获取输入或输出的异常
    print('IOError')

# 输出:IOError

try…except异常处理结构允许附带一个可选的else子句,用来设计当没有发生异常时,正常处理的代码块。else子句在异常发生时,不会被执行,只有当异常没有发生时才会执行。

try: # 捕获异常
    <执行语句>
except [异常类型][ as 别名]: # 处理异常
    <异常处理语句>
else: # 当异常未发生时执行
    <正常处理语句>

try:
    f = open('test.txt','r') # 打开文件
except:  # 如文件打开异常,则执行此
    print('出错了')
else: # 如文件正常打开,则执行此
    print(f.read()) # 读取文件内容

try:
    f = open('test.txt','r') # 打开文件
    print(f.read()) # 如文件打开异常,则不执行此
except: # 如文件打开异常,则执行此
    print('出错了')

善后处理try…except异常处理结构还可以带一个可选的finally子句,它表示无论异常是否发生,最后都要执行finally语句块。

try: # 捕获异常
    <执行语句>
except [异常类型][ as 别名]: # 处理异常
     <异常处理语句>
else: # 当异常未发生时执行
    <正常处理语句>
finally: # 不管异常是否发生,最后都要执行
    <最后必须处理语句>

import time 
i = 1 
while True: # 无限循环
    try:
        print(i) # 打印变量
        continue # 退出执行下一次循环
        print('永不执行') # 不执行该句
    finally: 
        time.sleep(1) # 暂停1s
        i += 1 # 递增变量
        continue # 退出执行下一次循环
        print('永不执行') # 不执行语句

抛出异常:使用raise语句主动抛出一个异常,这样可以确保程序根据开发人员的设计逻辑执行,也可以对用户的行为进行监控,避免意外操作。

raise [Exception[(args[,traceback])]]

raise 语句3种用法:

  • raise:单独一个raise。该语句将引发当前上下文捕获的异常,默认引发RuntimeError异常。
  • raise 异常类名称:raise 后带一个异常类名称,表示引发执行指定类型的异常。
  • raise 异常类名称(描述信息):在引发指定类型的异常时,显示异常的描述信息。
try:
    a = input('输入一个数')
    if (not a.isdigit()):
        raise
except RuntimeError as e:
    print('引发异常:',repr(e)) # 引发异常: RuntimeError('No active exception to reraise')

def test(num):
    try:
        if type(num) != int: # 如果为非数字的值,则抛出TypeError错误
            raise TypeError('参数不是数字') 
        if num <= 0: # 如果为非正整数,则抛出ValueError错误
            raise ValueError('参数为不大于0的整数')
        print(num) # 打印数字
    except Exception as e:
        print(e) # 打印错误信息
test('1') # 参数不是数字
test(0) # 参数为不大于0的整数
test(2) # 2

自定义异常:自定义异常类型必须直接或间接继承Exception类。

class MyError(Exception):
    def __init__(self,msg):
        self.msg=msg
    def __str__(self):
        return self.msg
try:
    raise MyError('自定义错误信息') # 主动抛出自定义错误
except MyError as e:
    print(e) # 打印:自定义错误信息

跟踪异常:使用traceback可以跟踪异常,记录异常发生时有关函数调用的堆栈信息。具体格式如下:

import traceback
try:
    1/0
except Exception as e:
    traceback.print_exc() # 打印详细的错误信息
    traceback.format_exc() # 格式化字符串的形式返回错误信息
    # 把错误信息直接保存到外部文件中
    traceback.print_exc(file=open('log.log',mode='a',encoding='utf-8'))

2. 程序调试

在编写程序中,常见错误有两种:语法错误和异常。语法错误又称解析错误,SyntaxError: invalid syntax 。

在这里插入图片描述

即使语句或表达式在语法上是正确的,但在执行时也可能会引发错误,该错误称为异常,异常如果不被捕获,被程序处理,则会中止程序,并显示异常提示信息。

在这里插入图片描述

使用assert语句可以定义断言,断言用于判断一个表达式,在表达式条件为Flase的时候触发异常,而不必等待程序运行后出现崩溃的情况。

def foo(s):
    n = int(s)
    assert n != 0,'n is zero!' # 设置断言
    return 10/n
def main():
    foo('0')

main()

# 在交互式模式中,可以使用-O参数关闭 assert
python -O test1.py

使用pdb,pdb 是Python自带的一个包,提供了一种交互的源代码调试功能,主要特性包括:设置断点、单步调试、进入函数调试、查看当前代码、查看栈片段、动态改变变量的值等。pdb常用的调试命令:

  • break或b:设置断点。
  • continue或c:继续执行程序。
  • list或l:查看当前行的代码段。
  • step或s:进入函数。
  • return或r:执行代码直到从当前函数返回。
  • exit或q:中止并退出。
  • next或n:执行下一行。
  • p val:打印变量的值。
  • help:帮助。
# 新建test1.py文件,代码如下
s = '0'
n = int(s)
print(10/n)
# cd 命令进入到test1.py文件所在目录
cd edition_master
# 启动pdb调试器
python -m pdb test1.py
# 执行操作
l # 查看当前行的代码段
n # 下一步
p s # 打印变量s
q # 退出

当程序代码较多时,在可能出错的地方插入pdb.set_trace(),则不需要单步执行。

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

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

相关文章

Redis集群环境各节点无法互相发现与Hash槽分配异常 CLUSTERDOWN Hash slot not served的解决方式

原创/朱季谦 在搭建Redis5.x版本的集群环境曾出现各节点无法互相发现与Hash槽分配异常 CLUSTERDOWN Hash slot not served的情况&#xff0c;故而把解决方式记录下来。 在以下三台虚拟机机器搭建Redis集群—— 192.168.200.160192.168.200.161192.168.200.162启动三台Redis集…

编程参考 - C++ Code Review: 一个计算器的项目

GitHub - jroelofs/calc: Toy Calculator Toy Calculator 1&#xff0c;拿到一个project&#xff0c;第一眼看&#xff0c;没有配置文件&#xff0c;说明没有引入持续集成系统&#xff0c;continuous integration system。 2&#xff0c;然后看cmake文件&#xff0c;使用的子…

安全地公网访问树莓派等设备的服务 内网穿透--frp 23年11月方法

如果想要树莓派可以被公网访问&#xff0c;可以选择直接网上搜内网穿透提供商&#xff0c;一个月大概10块钱&#xff0c;也有免费的&#xff0c;但是免费的速度就不要希望很好了。 也可以选择接下来介绍的frp&#xff0c;这种方式不需要付费&#xff0c;但是需要你有一台有着公…

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《交直流配电网中柔性软开关接入的规划-运行协同优化方法》

这个标题涉及到交直流配电网中柔性软开关接入的规划-运行协同优化方法。下面是对这个标题各部分的详细解读&#xff1a; 交直流配电网&#xff1a; 这指的是一个电力系统&#xff0c;同时包含交流和直流电力传输的元素。这样的系统可能结合了传统的交流电力传输和近年来兴起的直…

selinux-policy-default(2:2.20231119-2)软件包内容详细介绍(1)

1. 下载 (1)主页 地址如下: https://packages.debian.org/sid/selinux-policy-default 页面如下所示: (2)实际下载页面 下翻以上页面到底部。如下图所示: 点击页面中的“all”,出现以下页面: (3)实际下载 向下滑动页面,找到就近的服务器。这里选择“亚洲”下…

计算机网络——物理层相关习题(计算机专业考研全国统考历年真题)

目录 2012-34 原题 答案 解析 2018-34 原题 答案 解析 2009/2011-34 原题 答案 解析 2016-34 原题 答案 解析 2014-35/2017-34 原题 答案 解析 2013-34 原题 答案 解析 2015-34 原题 答案 解析 物理层的协议众多&#xff0c;这是因为物理层…

tp8 使用rabbitMQ(3)发布/订阅

发布/订阅 当我们想把一个消息&#xff0c;发送给 多个消费者的时候&#xff0c;我们把这种模式叫做发布/订阅模式&#xff0c;比如我们做两个消费者&#xff0c;其中一个消费者把消息写入磁盘中&#xff0c;别一个消费者把消息结果输出到屏幕上&#xff0c;就要用到发布订阅模…

leetcode刷题日志-70爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1 阶 1 阶2 阶 示例 2&#xff1a; …

牛气霸屏-快抖云推独立版V1.6.7

介绍 快抖云推全插件独立版是最近很火的牛气霸屏系统独立版&#xff0c;牛气霸屏系统就是商家通过系统在线创建抖音或快手霸屏活动&#xff0c;并生成该活动的爆客二维码&#xff0c;用户通过扫二维码即可参加活动&#xff08;活动可以是领取卡劵&#xff0c;抽奖等&#xff0…

RT-Thread 线程间通信【邮箱、消息队列、信号】

线程间通信 一、邮箱1. 创建邮箱2. 发送邮件3. 接收邮件4. 删除邮箱5. 代码示例 二、消息队列1. 创建消息队列2. 发送消息3. 接收消息4. 删除消息队列5. 代码示例 三、信号1. 安装信号2. 阻塞信号3. 解除信号阻塞4. 发送信号5. 等待信号6. 代码示例 一、邮箱 RT-Thread 操作系…

6个PPT素材网站,让你快速做出好看的PPT

找PPT模板一定要收藏好这6个网站&#xff0c;能让你快速做出好看的PPT&#xff0c;重点十可以免费下载&#xff0c;赶紧收藏&#xff01; 1、菜鸟图库 https://www.sucai999.com/search/ppt/0_0_0_1.html?vNTYwNDUx 菜鸟图库网有非常丰富的免费素材&#xff0c;像设计类、办公…

Linux系统介绍及文件类型和权限

终端:CtrlAltT 或者桌面/文件夹右键,打开终端 切换为管理员:sudo su 退出:exit 查看内核版本号:uname -a 内核版本号含义:5 代表主版本号;13代表次版本号;0代表修订版本号;30代表修订版本的第几次微调;数字越大表示内核越新. 目录结构 /bin:存放常用命令(即二进制可执行程序…

c++|类和对象(上)

目录 一、面向过程和面向对象初步认识 二、类的引入和定义 2.1类的引入 2.2类的定义 三、类的访问限定符及封装 3.1访问限定符 3.2封装 四、类的作用域 五、类的实例化 六、类的对象大小的计算 6.1如何计算对象的大小 6.2类对象的存储方式 七、类成员函数的thi…

OpenCV快速入门:图像分析——傅里叶变换、积分图像

文章目录 前言一、傅里叶变换1.1 离散傅里叶变换1.1.1 离散傅里叶变换原理1.1.2 离散傅里叶变换公式1.1.3 代码实现1.1.4 cv2.dft 函数解析 1.2 傅里叶变换进行卷积1.2.1 傅里叶变换卷积原理1.2.2 傅里叶变换卷积公式1.2.3 代码实现1.2.4 cv2.mulSpectrums 函数解析 1.3 离散余…

LangChain的简单使用介绍

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

解决kubernetes中微服务pod之间调用失败报错connection refused的问题

现象&#xff1a; 从这里可以看到是当前服务在调用product service服务是出现了连接拒绝connection refused 走读一下原始代码&#xff1a; 可以看到请求是由FeignClient代理发出的 &#xff0c;但问题在于为什么Feign请求的时候会产生connection refused错误&#xff1f; 上…

Python+jieba+wordcloud实现文本分词、词频统计、条形图绘制及不同主题的词云图绘制

目录 序言&#xff1a;第三方库及所需材料函数模块介绍分词词频统计条形图绘制词云绘制主函数 效果预览全部代码 序言&#xff1a;第三方库及所需材料 编程语言&#xff1a;Python3.9。 编程环境&#xff1a;Anaconda3&#xff0c;Spyder5。 使用到的主要第三方库&#xff1a;…

飞书+ChatGPT搭建智能AI助手并实现公网访问web界面

文章目录 前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 前言 在飞书中创建chatGPT机器人并且对话&#xff0c;在下面操作步骤中…

时间序列分析算法的概念、模型检验及应用

时间序列分析是一种用于研究随时间变化的数据模式和趋势的统计方法。这类数据通常按照时间顺序排列&#xff0c;例如股票价格、气温、销售额等。时间序列分析的目标是从过去的观测中提取信息&#xff0c;以便预测未来的趋势。 以下是关于时间序列分析的一些重要概念、模型检验…

【深度学习】学习率及多种选择策略

学习率是最影响性能的超参数之一&#xff0c;如果我们只能调整一个超参数&#xff0c;那么最好的选择就是它。相比于其它超参数学习率以一种更加复杂的方式控制着模型的有效容量&#xff0c;当学习率最优时&#xff0c;模型的有效容量最大。本文从手动选择学习率到使用预热机制…