Python中的异常(Exception)

以下 Python 版本为 Python 3.8.10 .

初探异常

错误:

  • 语法错误 .
  • 逻辑错误 .

异常:程序运行过程中,出现的意料之外的错误(大概类似 corner case),例如除 0(ZeroDivisionError),尾迭代器自增(StopIteration),解包一个 int 等(TypeError),其他异常见「常见异常」.

很明了吧 .

我们平时写 Python 码写出 bug 则解释器会报错(运行时),这个就是 Traceback .

处理用户未处理的异常的方法就是先终止程序,再通过 Traceback(堆栈回溯,也称向后追踪)来显示异常发生的上下文 .

我们可以通过引用 traceback 模块来访问 Traceback .

Python 异常 解释

所有异常的基类

解释器请求退出

用户中断执行(通常是输入

常规错误的基类

迭代器越界

生成器异常于是通知退出

Python 解释器请求退出

所有的内建标准异常的基类

所有数值计算错误的基类

浮点计算错误

数值运算超出最大限制(上溢)

除 / 取模零(所有数据类型)

断言 (assert) 异常

对象没有这个属性

输入读到 EOF

操作系统错误的基类

输入 / 输出操作失败

操作系统错误

系统调用失败

导入模块/对象失败

无效数据查询的基类

序列 (list) 中找不到要调用的索引

映射 (map) 中找不到要调用的键

内存溢出

未声明 / 初始化对象

访问未初始化的本地变量

弱引用试图访问已经垃圾回收了的对象

一般的运行时错误

调用没有的方法

语法错误

缩进错误

Tab 和空格混用

一般的解释器系统错误

对类型无效的操作

传入无效的参数(类型不对)

Unicode 相关的错误

Unicode 解码时的错误

Unicode 编码时错误

Unicode 转换时错误

所有警告的基类

关于被弃用的特征的警告

关于构造将来语义会有改变的警告

旧的关于自动提升为长整型 (long) 的警告

关于特性将会被废弃的警告

可疑的运行时行为的警告

可疑的语法的警告

用户代码生成的警告

异常处理

这个可以类比 C++ 中的 try ... catch,不过 Python 异常更灵活一点(因为解释性甚至连 C++ 中一些引发编译错误 (Compile Error, CE) 的内容都能补救回来)

平凡的处理方法是 try ... except

try:
    代码
except 错误类型A as 接受错误信息的变量A:
    处理代码A
except 错误类型B as 接受错误信息的变量B:
    处理代码B
...

except 里面啥都不填就是自动捕获所有异常 .

接受处理的变量,设为 e,则可以做:

  • str(e) / e.message,只给出异常信息的字符串,不包括异常信息的类型 .
  • repr(e),给出较全的异常信息,包括异常信息的类型 .
  • 使用 traceback 模块,此时获取的信息最全,与 Python 解释器运行程序出现错误信息一致,下面是两个常用方法:
  • traceback.print_exc() 打印异常信息到标准错误流 (stderr) .
  • traceback.format_exc() 将同样的输出获取为字符串 . 其余用法请查阅文档 .
  • 使用 sys 模块: sys.exc_info() 方法可以获取正在处理的异常信息,即 except 子句正在处理的异常,其返回值为一个 tuple 类型的三元组 (exc_type, exc_value, exc_traceback),其中, exc_type 为获取到的异常类型; exc_value 为该异常类型对象; exc_traceback 为一个 traceback 对象,包含异常最初发生的调用栈信息 .
    例子:
a = 10
b = 0
try:
    c = a / b
    print(c)
except ZeroDivisionError as e:
    print(str(e))
    print(repr(e))

print("done")

输出:

division by zero
ZeroDivisionError('division by zero')
done

另外,这个错误类型可以列举,例如:

Python 3
a = 10
b = 0
try:
    c = b / a
    print(c)
except (IOError, ZeroDivisionError) as x:
    print(x)
else:
    print("no error")

print("done")

输出:

0.0
no error
done

我们发现上面的实例中出现了一个 else 字句,这个的意思估计大家也能猜出来吧 —— 没有异常的时候进行的操作 .

一个完整的 try... 语法结构实际上应该包含 exceptelsefinally 子句,形如:

try:
    ...

except 异常1 as 异常信息1:
    ...

except 异常2 as 异常信息2:
    ...

except:
    ...

else:
    ... # 这里是没有异常时执行的
finally:
    ... # 这里是不管有没有异常最后都执行一下的

我觉得也不需要放实例,非常的明了 .

注意尽量不要在 try ... 语句中使用 raisereturn 这种可能退出程序的语句,例如:

def foo(x):
    try:
        x += 1
        return x
    finally:
        return x+1

print(foo(11))

输出:

13

这说明, try ... except 语句中使用 return 实际上 finally 子句是会执行的 .

具体的:

  • 在函数中的 try ... except 语句使用 return 后,仍然会执行 finally 中的内容 .
  • finally 使用 return 会导致异常无法回溯 .

还有就是关于性能了,我们尽量是少让它 try ... except,例如下面这个实例:

for i in range(114514):
    try:
        pass
    except:
        pass

就可以改写为

try:
    for i in range(114514):
        pass
except:
    pass

raise 可以抛出一个异常,例如:

print(114514)
raise SyntaxError
print(1919810)

这样中间就会出一个 SyntaxError .

SyntaxError 实际上是一个类,抛出异常时,会自动生成它的一个对象,Python 实际上抛出的是这个对象 .

当然,也可以自行生成对象:

raise SyntaxError()

我觉得异常还是 Python 中比较基础的知识点,希望大家掌握 .

以下是 OI 特供版内容:

在 OI 中的应用

我们知道 Python 读没了会抛出 EOFError .

所以 try ... except 一下就可以判断读没读完,也就可以实现不定行读入了 .

中缀表达式
输入一个中缀表达式(由 (0\dots9) 组成的运算数,加 +-*/(除为整除)四种运算符,左右小括号组成 . 注意 - 也可作为负数的标志,表达式以 @ 作为结束符),判断表达式是否合法,如果不合法,输出 NO;否则请把表达式转换成后缀形式,再求出后缀表达式的值并输出 .

黑盒测试不用管转换后缀表达式,只需要求值即可 .

一开始先把 @ 去掉,这个非常平凡 .

然后 Python 有方法 eval 可以返回一行 Python 语句返回的结果,就像在解释器中直接输入一样 .

这样我们就可以直接使用 eval 来计算了 .

注意这里的除是整除所以要先把 / 全部 replace//,这样才符合 Python 语法 .

eval 如果运行不下去了就会抛出异常,我们根据这个来判断 NO 即可 .

注意抛出的不一定是 SyntaxError,比如下面这组数据:

(5*(5-9)-4)+7-9*2+5(*(+6-2))@

eval 会抛出 TypeError .

下面是完整代码:

import traceback
s = input().split('@')[0].replace("/", "//")
try:
    print(eval(s))
except:
    print("NO")
    traceback.print_exc() # debug

Original: https://www.cnblogs.com/CDOI-24374/p/16611179.html
Author: Jijidawang
Title: Python中的异常(Exception)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/712064/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • STM32 例程-7 STM32固件库方式 读取SHT20 温湿度

    SHT20 .h文件 #ifndef SHT20_H #define SHT20_H #include "common.h" #include "st…

    技术杂谈 2023年6月1日
    0109
  • php: 单下划线函数意义

    待完善参考 posted @2022-09-21 09:42 CodeWater 阅读(24 ) 评论() 编辑 Original: https://www.cnblogs.com…

    技术杂谈 2023年7月25日
    076
  • Vue(十三)—过滤器filter,filters

    官网:https://cn.vuejs.org/v2/api/#filters https://cn.vuejs.org/v2/api/#Vue-filter 分为全局过滤器和局部…

    技术杂谈 2023年7月25日
    074
  • 突破

    象棋的目标是赢棋,而不是谋子。突破了「谋子」这一认知的棋手,招式中就多了欲擒故纵。甚至棋手心里都没想着招式,只是在朝着目标布局。 象棋的目标是赢棋,而不是谋子。突破了「谋子」这一认…

    技术杂谈 2023年7月11日
    061
  • 规则引擎深度对比,LiteFlow vs Drools!

    前言 Drools是一款老牌的java规则引擎框架,早在十几年前,我刚工作的时候,曾在一家第三方支付企业工作。在核心的支付路由层面我记得就是用Drools来做的。 难能可贵的是,D…

    技术杂谈 2023年7月11日
    080
  • mac查看当前调用tcp的进程并关闭指定进程

    查看所有tcp进程 监听的端口 lsof -iTCP -sTCP:LISTEN 查看指定端口信息 lsof -i:12345 关闭指定进程 kill -9 52356 Origin…

    技术杂谈 2023年5月30日
    091
  • iPhone设置微信Callkit

    国内的苹果手机的微信接听没有提醒,主要原因是出于种种原因微信限制了Callkit。如果想要锁屏接听,像接电话一样。方式一是更换绑定境外的手机号。这里使用Google Voice的虚…

    技术杂谈 2023年6月1日
    0192
  • Jenkins安装(Docker)版

    一、jenkins安装 1.查找,下载jenkins镜像文件 启动docker,查找Jenkins镜像文件 docker search jenk…

    技术杂谈 2023年7月11日
    071
  • HINT: Add or change a related_name argument to the definition for ‘usersApp.

    错误原因是你的项目使用的不是Django自带的用户表,采用的自定义的用户表,这个时候需要在settings.py里面进行指定。 AUTH_USER_MODEL = ‘usersAp…

    技术杂谈 2023年7月11日
    085
  • Malformed UTF-8 characters, possibly incorrectly encoded

    PHP 报错: [ error ] [0]Malformed UTF-8 characters, possibly incorrectly encoded 原因:返回的内容用 UT…

    技术杂谈 2023年5月31日
    077
  • Android进阶技术之——一文吃透Android的消息机制

    前言 为什么要老药换新汤 作为Android中 至关重要 的机制之一,十多年来,分析它的文章不断,大量的内容已经被挖掘过了。所以: 已经对这一机制熟稔于心的读者,在这篇文章中,看不…

    技术杂谈 2023年7月10日
    080
  • go语言接口

    接口在底层的实现有两个部分:type 和 data。 在源码中,显式地将 nil 赋值给接口时,接口的 type 和 data 都将为 nil。此时,接口与 nil 值判断是相等的…

    技术杂谈 2023年7月11日
    066
  • nginx location配置详细解释

    【原文链接】:https://blog.tecchen.xyz ,博文同步发布到博客园。由于精力有限,对文章的更新可能不能及时同步,请点击上面的原文链接访问最新内容。欢迎访问我的个…

    技术杂谈 2023年7月11日
    058
  • Linux中的fd

    Linux中的fd 起子 ​ 如果说系统学Linux,我其实没有这个经历,你问我xx环境在Linux内核某个发行版怎么配置,那我可能可以告诉你,但是你要问我很多kernel相关的内…

    技术杂谈 2023年7月11日
    079
  • 八、变量与常量

    一、变量 1.1、变量的基本概念 Java是一种强类型语言,每个变量都必须声明其类型。Java变量是程序中最基本的存储单元,其要素包括变量名、变量类型和作用域。 type varN…

    技术杂谈 2023年6月21日
    0107
  • Linux特殊权限之suid、sgid、sbit权限

    文件权限管理之特殊命令 一:特殊权限 昨天所学的Linux基本权限为为9个;分别是rwx rwx rwx。但有时会发现系统中会有一些特殊的权限位符号; 例如: Linux系统一共有…

    技术杂谈 2023年7月11日
    0106
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球