Python程序异常处理

news2024/11/28 6:52:24

一、什么是异常

异常就是程序运行时发生错误的信号,在程序由于某些原因出现错误的时候,若程序没有处理它,则会抛出异常,程序也的运行也会随之终止;

  • 程序异常带来的问题:

1.程序终止,无法运行下去;  2…如果程序是面向客户,那么会使客户的体验感很差,进而影响业务;

  • 什么时候容易出现异常:

当处理不确定因素时,比如有用户参与,有外界数据传入时,都容易出现异常;

  • 产生异常事件大致分两种:
    1.由于语法错误导致程序出现异常,这种错误,根本过不了Python解释器的语法检查,必须在程序执行前就改正;
#语法错误示范一:
if

#语法错误示范二:
def func:

#语法错误示范三:
class foo
    pass

#语法错误示范四:
print(hello word

2.就是由于代码的逻辑问题使程序产生了异常;

#错误示例:
for n in 3:
    pass

#错误示例:
[][1]

二、异常的类型

异常也是有分类的,不同的异常用不同的类型去标识,不同的类对象标识不同的异常,一个异常标识一种错误;

常用的异常种类:

'''
AttributeError            #试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError                      # 输入/输出异常;基本上是无法打开文件
ImportError               #无法引入模块或包;基本上是路径问题或名称错误
IndentationError        #语法错误(的子类) ;代码没有正确对齐
IndexError                 #下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError                     #试图访问字典里不存在的键
KeyboardInterrupt      #Ctrl+C被按下
NameError                  #使用一个还未被赋予对象的变量
SyntaxError                #Python代码非法,代码不能编译,其实是语法错误;
TypeError                    #传入对象类型与要求的不符合
UnboundLocalError      #试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
ValueError                   #传入一个调用者不期望的值,即使值的类型是正确的

'''                    

在这里插入图片描述

三、异常处理机制

先来看看程序异常后,怎么报的错,我们从报错中能够分析出什么。
在这里插入图片描述

什么是异常处理?

python解释器检测到错误,触发异常(也允许程序员自己触发异常),程序员编写特定的代码,专门用来捕获这个异常(这段特点代码与逻辑程序无关和异常处理有关);如果捕获成功则进入另一个处理分支,执行为其定制的逻辑,使程序不会崩溃,这就是异常处理。

为什么要进行异常处理?

python解释器去执行程序,检测到一个错误时,触发异常,异常触发后且没有被处理的情况下,程序就在当前异常处停止运行,后面的代码不会执行,那么没有人会去使用一个运行着突然就崩溃的软件的;所以我们有必要提供一种异常处理机制来增强程序的健壮性和容错性。

如何进行异常处理?

首先须知,异常是由程序的错误引起的,语法上的错误跟异常处理无关,必须在程序运行前就修正;

1.使用if判断式
num1=input('>>: ') #输入一个字符串试试
int(num1)

使用if判断进行异常处理

num1=input('>>: ') #输入一个字符串试试
if num1.isdigit():
    int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴
elif num1.isspace():
    print('输入的是空格,就执行我这里的逻辑')
elif len(num1) == 0:
    print('输入的是空,就执行我这里的逻辑')
else:
    print('其他情情况,执行我这里的逻辑')

问题一:
使用if的方式我们只为第一段代码加上了异常处理,但这些if,跟你的代码逻辑并无关系,这样你的代码会因为可读性差而不容易被看懂

问题二:
这只是我们代码中的一个小逻辑,如果类似的逻辑多,那么每一次都需要判断这些内容,就会倒置我们的代码特别冗长。

小结:

1.if判断式的异常处理只能针对某一段代码,对于不同的代码段的相同类型的错误你需要写重复的if来进行处理;

2.在你的程序中频繁的写与程序本身无关,与异常处理有关的if,会使得你的代码可读性极其的差;

3.if是可以解决异常的,只是存在1,2的问题,所以,千万不要妄下定论if不能用来异常处理;

之前用来判断异常的方法,比如不能输入数字或字母等等

def test():
    print('test running')
choice_dic={
    '1':test
}
while True:
    choice=input('>>: ').strip()
    if not choice or choice not in choice_dic:continue #这便是一种异常处理机制啊
    choice_dic[choice]()
2.python为每一种异常定制了一个类型,然后提供了一种特定的语法结构来进行异常处理;

首先重要的几种搭配格式列出来:

try ... except

try ... except ... else

try ... finally

try ... except ... finally

try ... except ... else ... finally
1)基本语法

异常处理的基本语法

try:
     被检测的代码块
except 异常类型:
     try中一旦检测到异常,就执行这个位置的逻辑

异常处理例子

try:
    a = "A"
    b
except NameError:
    print("b没有赋值会引发程序异常,异常类型时NameError,我们通过"
          "捕获这个异常,使其不会崩溃,继而执行此分支,也就是当前"
          "打印的这段话")

---------------------  运行后的效果 ----------------------------------------------
b没有赋值会引发程序异常,异常类型时NameError,我们通过捕获这个异常,使其不会崩溃,继而执行此分支,也就是当前打印的这段话
2)异常类只能用来处理指定的异常情况,如果非指定异常则无法处理;
try:
    a = "A"
    b
except IndexError:
    print("b没有赋值会引发程序异常,异常类型时NameError,我们通过"
          "捕获这个异常,使其不会崩溃,继而执行此分支,也就是当前"
          "打印的这段话")

-------------------- 运行后的效果  -----------------------------------------------
Traceback (most recent call last):
  File "E:/python/s15/异常处理.py", line 3, in <module>
    b
NameError: name 'b' is not defined

因为我们设置的捕获异常类和其发生异常的类不是一个类,所以捕获不到;

3)多分支

说明:从上向下报错的代码只要找到一个和报错类型相符的分支就执行这个分支中的代码,然后直接退出分支;如果找不到能处理和报错类型相同的分支,会一直往下走,最后还是没有找到就会报错。

多分支异常处理

s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)

这里我们需要知道的是as的已是就是将捕获到的异常的内容赋值给变量e,变量e是不固定的,也可以使用其他字母来代替,这样的话,既方便我们对异常的内容进行分析,也不影响程序的执行。

4)多分支合并

说明:如果说我们有多个异常在处理时需要共同处理,比如说,只要发生IndexError和NameError异常了,我们就执行或打印一段代码时,就可以使用多分支合并的方式了;

多分支合并例子

l = ['login','register']
for num,i in enumerate(l,1):
     print(num,i)

  try:
     num = int(input('num >>>'))
     print(l[num - 1])
  except (ValueError,IndexError) :
     print('您输入的内容不合法')
5)万能异常;

说明:在python的异常中,有一个万能异常:Exception,它可以捕获任意异常;

s1 = 'hello'
try:
    int(s1)
except Exception as e:
    print(e)

注意:万能异常应该分两种情况去看;

  • 如果想要的效果是,无论出现什么异常,我们统一丢弃,或者使用同一段代码逻辑去处理他们,那么只有一个Exception就足够了。

  • 如果你想要的效果是,对于不同的异常我们需要定制不同的处理逻辑,那就需要用到多分支了

多分支+Exception

s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)
except Exception as e:
    print(e)
6)as用法:

说明:能够将具体错误信息打印出来,赋值给变量;

7)异常的其他机构,else,finally;

else 说明:当try内的代码块没有报错时并且还要继续运行程序的话就用else;

finally 说明:无论try内的代码块是否异常,都执行该区域内的代码,通过用来进行清理工作;尤其注意如果在函数中有finally,即使return也会先执行fianlly中的代码。

else 以及 finally

s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)
#except Exception as e:
#    print(e)
else: #Python小白交流学习群:711312441
    print('try内代码块没有异常则执行我')
finally:
    print('无论异常与否,都会执行该模块,通常是进行清理工作')
8)主动触发异常 raise;

说明:这是给开发者用的,比如我们现在用的python,作者就会在python中加入主动触发异常,就是用来给开发者的,当遇到异常时会报错,提示开发者;

>>> try:
...     raise TypeError('类型错误')
... except Exception as e:
...     print(e)
... 
类型错误
9)断言 语法

说明:assert断言语句用来声明某个条件是真的,其作用是测试一个条件(condition)是否成立,如果不成立,则抛出异常。

语法:assert condition

如果condition为false,就raise一个AssertionError出来。逻辑上等同于:

if not condition:
    raise AssertionError()

assert condition,expression

如果condition为false,就raise一个描述为 expression 的AssertionError出来。逻辑上等同于:

if not condition:
        raise AssertionError(expression)

使用例子:

assert 断言例子

>>> assert 1 == 1
>>> assert 1 == 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>> assert 1 == 2,"这是什么鬼"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: 这是什么鬼
10)自定义异常

在我们自定义返回异常时,最好使用异常code + 异常data的方式;看一个例子:

#去path路径的文件中,找到前缀为prev的一行数据,获取数据并返回给调用者。
#code值+data
#1000,成功
#1001,文件不存在
#1002,关键字为空
#1003,未知错误

#方法一:
import os
def func(path,prev):
    """
    去path路径的文件中,找到前缀为prev的一行数据,获取数据并返回给调用者。
        1000,成功
        1001,文件不存在
        1002,关键字为空
        1003,未知错误
        ...
    :return:
    """
    response = {'code':1000,'data':None}
    try:
        if not os.path.exists(path):
            response['code'] = 1001
            response['data'] = '文件不存在'
            return response
        if not prev:
            response['code'] = 1002
            response['data'] = '关键字为空'
            return response
        pass  #业务代码区
    except Exception as e:
        response['code'] = 1003
        response['data'] = '未知错误'
    return response



#方法二:
import os

class ExistsError(Exception):
    pass

class KeyInvalidError(Exception):
    pass

def new_func(path,prev):
    """
    去path路径的文件中,找到前缀为prev的一行数据,获取数据并返回给调用者。
        1000,成功
        1001,文件不存在
        1002,关键字为空
        1003,未知错误
        ...
    :return:
    """
    response = {'code':1000,'data':None}
    try:
        if not os.path.exists(path):
            raise ExistsError()

        if not prev:
            raise KeyInvalidError()
        pass
    except ExistsError as e:
        response['code'] = 1001
        response['data'] = '文件不存在'
    except KeyInvalidError as e:
        response['code'] = 1002
        response['data'] = '关键字为空'
    except Exception as e:
        response['code'] = 1003
        response['data'] = '未知错误'
    return response



##方法三:
class MyException(Exception):
    def __init__(self,code,msg):
        self.code = code
        self.msg = msg
try:  #Python小白交流学习群:711312441
    raise MyException(1000,'操作异常')
    pass
except KeyError as obj:
    print(obj,1111)
except MyException as obj:
    print(obj,2222)
except Exception as obj:
    print(obj,3333)
----------------------- 打印结果 -------------------------------------------
(1000, '操作异常') 2222

try方式比较if的方式的好处:

try…except这种异常处理机制就是取代if那种方式,让你的程序在不牺牲可读性的前提下增强健壮性和容错性,异常处理中为每一个异常定制了异常类型(python中统一了类与类型,类型即类),对于同一种异常,一个except就可以捕捉到,可以同时处理多段代码的异常(无需‘写多个if判断式’)减少了代码,增强了可读性 ;

使用try…except的方式:

  • 把错误处理和真正的工作分开来

  • 代码更易组织,更清晰,复杂的工作任务更容易实现

  • 毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了

什么时候用异常处理?

try…except应该尽量少用,因为它本身就是你附加给你的程序的一种异常处理的逻辑,与你的主要的工作是没有关系的

这种东西加的多了,会导致你的代码可读性变差,只有在有些异常无法预知的情况下,才应该加上try…except,其他的逻辑错误应该尽量修正

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

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

相关文章

浙大数据结构(1)

开始学习数据结构(拖了好久终于开干了) 来自【浙江大学】数据结构&#xff08;合149讲&#xff09;陈越 何钦铭 Be a Fighter and Keep Fighting!!! 数据结构(data structure)定义 是计算机中存储&#xff0c;组织数据的方法。通常情况下&#xff0c;精心选择的数据结构可以带…

Chapter7-吞吐量优先的使用场景

7.1 在 Broker 端进行消息过滤 在 Broker 端进行消息过滤&#xff0c;可以减少无效消息发送到 Consumer &#xff0c;少占用网络带宽从而提高吞吐量。 Broker 端有三种方式进行消息过滤 。 7.1.1 消息的 Tag 和 Key 对一个应用来说&#xff0c;尽可能只用一个 Topic &#xff…

【数据结构学习3】线性表-链表、单链表

目录链式存储结构链表概念头结点的意义单链表的定义和表示单链表的基本操作链式存储结构 链表概念 概念 结点在存储器中的位置是任意的&#xff0c;即逻辑上相邻的数据元素在物理上不一定相邻。线性表的链式表示又称为非顺序映像或链式映像用一组物理位置任意的存储单元来存…

三公经费用泛微全过程数字化管理,使用有记录,付款有依据

公开透明是现代财政制度的重要准则和基本特征。组织要以公开、透明、科学的预算制度确定财政支出&#xff0c;贯穿预算编制、执行、监督全过程。 组织常见的费用管理——“三公”经费&#xff0c;通常指因公出国&#xff08;境&#xff09;费、公务用车购置及运行费、公务接待…

富士康转移3000亿产能,iPhone的印度产能倍增,不再“赏饭吃”

日前消息指今年三月份印度的iPhone产量已经是去年的四倍之多&#xff0c;占比将近7&#xff05;&#xff0c;显示出苹果和富士康都在加速提升印度的iPhone产能&#xff0c;凸显出他们的决心&#xff0c;这对中国制造业将带来深远影响。一、富士康对中国制造影响巨大2021年的数据…

leetcode每日一题:数组篇(1/2)

&#x1f61a;一个不甘平凡的普通人&#xff0c;日更算法学习和打卡&#xff0c;期待您的关注和认可&#xff0c;陪您一起学习打卡&#xff01;&#xff01;&#xff01;&#x1f618;&#x1f618;&#x1f618; &#x1f917;专栏&#xff1a;每日算法学习 &#x1f4ac;个人…

key的作用和原理、列表过滤

一、key的作用与原理 虚拟DOM对象的标识。当状态中的数据发生变化时&#xff0c;vue会根据新数据生成新的虚拟DOM。随后vue进行新虚拟DOM与旧虚拟DOM的差异比较&#xff0c;规则如下&#xff1a;对比规则&#xff1a; 旧虚拟DOM中找到了与新虚拟DOM相同的key 若虚拟DOM中内容没…

Iceberg 数据湖是什么?数据湖能解决什么问题?独立于计算层和存储层之间的表格层?

Iceberg 数据湖是什么&#xff1f;数据湖能解决什么问题&#xff1f;独立于计算层和存储层之间的表格层&#xff1f;0. 导读1. Hive数仓遇到的问题2. 一种开放的表格式3. 自下而上的元数据4. 高性能的查询4.1 分区剪裁4.2 文件过滤4.3 RowGroup过滤参考&#xff1a;https://ice…

kafka-4 生产者和消费者

kafka的生产者和消费者四、 生产者4.1 分区分配策略4.2 副本和消息消费4.2.1 副本&#xff08;AR、ISR、OSR&#xff09;4.2.2 HW与LEO4.2.3 ISR 集合和 HW、LEO的关系五、消费者5.1 分区分配策略5.2 消费者offset的存储四、 生产者 4.1 分区分配策略 &#xff08;1&#xff…

【20】linux进阶——linux的数据流和重定向

大家好&#xff0c;这里是天亮之前ict&#xff0c;本人网络工程大三在读小学生&#xff0c;拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识&#xff0c;希望能提高自己的技术的同时&#xff0c;也可以帮助到大家 另外其它专栏请关注&#xff1a; 锐捷数通实验&…

一、LED子系统框架分析

个人主页&#xff1a;董哥聊技术我是董哥&#xff0c;嵌入式领域新星创作者创作理念&#xff1a;专注分享高质量嵌入式文章&#xff0c;让大家读有所得&#xff01;文章目录1、前言2、LED裸机处理3、LED子系统框架4、LED子系统目录结构及核心文件5、sysfs目录结构5.1 确保LED子…

低代码开发重要工具:私有化部署的jvs-logic的设计与价值

逻辑引擎介绍 逻辑引擎是一种能够处理逻辑表达式的程序&#xff0c;它能够根据用户输入的表达式计算出表达式的值。在实际应用中&#xff0c;逻辑引擎通常被用于处理规则引擎、决策系统、业务规则配置等领域&#xff0c;具有广泛的应用前景。 逻辑引擎如下图所示&#xff0c;在…

Hive中SQL基本操作

文章目录1. Hive 中DDL1) 数据库操作2) 创建表 Create table3&#xff09;内部外部表区别4) Create Table As Select (CTAS)4&#xff09;分区表 partition2 .Hive中 DML1&#xff09;从文件加载数据 Loading files into tables2&#xff09;插入 INSERT3&#xff09;更新 UPDA…

《疯狂Java讲义》读书笔记7

Navicat快捷键 刷新&#xff1a;FnF5 表内容页面打开表设计页面&#xff1a;CtrlD 打开 MYSQL 命令行窗口&#xff1a;FnF6 MYSQL 增减查改 create table student(stuid int not null auto_increment primary key,stuname varchar(200),stustatus varchar(100) ); create …

TCP/IP协议工作原理与工作流程

一、TCP/IP协议工作原理 1、OSI模型 使用OSI模型来描述一个网络中的各个协议层&#xff0c;如下&#xff1a; 2、理解TCP/IP协议 TCP/IP协议&#xff0c;英文全称Transmission Control Protocol/Internet Protocol&#xff0c;包含了一系列构成互联网基础的网络协议&#xff0…

本地部署ChatGLM-6B模型(使用JittorLLMs大模型推理库)

简介 网上冲浪时发现的这两个国产模型&#xff0c;重点是对硬件的要求并不高&#xff0c;有2GB内存就可以跑&#xff0c;觉得有趣就弄来玩了下。 https://github.com/Jittor/JittorLLMs https://github.com/THUDM/ChatGLM-6B 简单介绍下用到的仓库 ChatGLM-6B ChatGLM-6B 是…

有偏估计的发展及其在球谐函数拟合中的应用研究

有偏估计的发展及其在球谐函数拟合中的应用研究 阚昊宇 专业&#xff1a;大地测量与测量工程 学号&#xff1a;XXX 邮箱&#xff1a;XXX 电话&#xff1a;XXX 摘要&#xff1a;球谐函数在大地测量等领域具有重要意义&#xff0c;然而在观测量不多或空间分布不均匀时进行高阶…

视频编解码(一)之virtio-gpu环境搭建

一、基础概念 VA-API Video Acceleration API 是一组开源应用API接口&#xff0c;赋能应用&#xff08;比如VLC播放器、GStreamer等&#xff09;使用hardware video acceleration&#xff08;一般是GPU提供硬件视频加速功能&#xff09;&#xff0c;VA-API主要由开源库libva和…

机器学习算法系列(三)

机器学习算法之–对数几率回归&#xff08;逻辑斯蒂回归&#xff09;算法 上个算法&#xff08;算法系列二&#xff09;介绍了如何使用线性模型进行回归学习&#xff0c;但若要做的是分类任务&#xff0c;则需要找一个单调可微函数将分类任务的真实标记y与线性回归模型的预测值…

Scons自动大型系统构建工具

1、先了解一下make 在Linux系统上做过c/c++开发的同学们都知道一个项目工程管理工具:make和Makefile。 make 这个工具自上个世纪 70 年代 Stuart Feldman 在贝尔实验室开发出以来,就一直是类 UNIX 程序员的最爱之一。 通过检查文件的修改时间,make 工具可以知道编译目标文…