125.异常的本质_调试核心理念
异常指程序运行过程中出现的非正常现象,例如用户输入错误、除数为零、需要处理的文件不存在、数组下标越界等。
所谓异常处理,就是指程序在出现问题时依然可以正确的执行剩余的程序,而不会因为异常而终止程序执行。
python 中,引进了很多用来描述和处理异常的类,称为异常类。异常类定义中包含了该类异常的信息和对异常进行处理的方法。下面较为完整的展示了python 中内建异常类的继承层次:
python 中一切都是对象,异常也采用对象的方式来处理。处理过程:
1.抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给解释器。
2.捕获异常:解释器得到该异常后,寻找相应的代码来处理该异常。
126.try_一个except基本结构
try:
被监控的可能引发异常的语句块
except BaseException [as e]:
异常处理语句块
try 块包含着可能引发异常的代码,except 块则用来捕捉和处理发生的异常。执行的时候,如果 try 块中没有引发异常,则跳过 except 块继续执行后续代码;执行的时候,如果 try块中发生了异常,则跳过 try 块中的后续代码,跳到相应的 except 块中处理异常;异常处理完后,继续执行后续代码。
try:
print("step1")
a = 3/0
print("step2")
except BaseException as e:
print("step3")
print(e)
print("step4")
step1
step3
division by zero
step4
127.try_多个except结构
上面的结构可以捕获所有的异常,工作中也很常见。但是,从经典理论考虑,一般建议尽量捕获可能出现的多个异常(按照先子类后父类的顺序),并且针对性的写出异常处理代码。为了避免遗漏可能出现的异常,可以在最后增加 BaseException。结构如下:
try:
被监控的、可能引发异常的语句块
except Exception1:
处理 Exception1 的语句块
except Exception2:
处理 Exception2 的语句块
...
except BaseException:
处理可能遗漏的异常的语句块
try:
a = input("请输入被除数:")
b = input("请输入除数:")
c = float(a)/float(b)
print(c)
except ZeroDivisionError:
print("异常:除数不能为 0")
except TypeError:
print("异常:除数和被除数都应该为数值类型")
except NameError:
print("异常:变量不存在")
except BaseException as e:
print(e)
print(type(e))
128.try...except...else结构
try...except...else 结构增加了“else 块”。如果 try 块中没有抛出异常,则执行 else 块。如果try 块中抛出异常,则执行 except 块,不执行 else 块。
try:
a = input("请输入被除数:")
b = input("请输入除数:")
c = float(a)/float(b)
except BaseException as e:
print(e)
else:
print("除的结果是:",c)
129.try...except...finally结构
try...except...finally 结构中,finally 块无论是否发生异常都会被执行;通常用来释放 try 块中申请的资源。
try:
a = input("请输入一个被除数:")
b = input("请输入一个除数:")
c = float(a)/float(b)
except BaseException as e:
print(e)
else:
print(c)
finally:
print("我是 finally 中的语句,无论发生异常与否,都执行!")
print("程序结束!")
try:
f = open("d:/a.txt",'r')
content = f.readline()
print(content)
except BaseException as e:
print(e)
finally:
print("关闭资源")
try:
f.close()
except BaseException as e:
print(e)
print("程序关闭")
130.常见异常汇总和说明
return 语句和异常处理问题
由于 return 有两种作用:结束方法运行、返回值。我们一般不把 return 放到异常处理结构中,而是放到方法最后。
常见异常的解决
异常名称 | 说明 |
ArithmeticError | 所有数值计算错误的基类 |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
BaseException | 所有异常的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
EnvironmentError | 操作系统错误的基类 |
EOFError | 没有内建输入,到达EOF 标记 |
Exception | 常规错误的基类 |
FloatingPointError | 浮点计算错误 |
FutureWarning | 关于构造将来语义会有改变的警告 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
ImportError | 导入模块/对象失败 |
IndentationError | 缩进错误 |
IndexError | 序列中没有此索引(index) |
IOError | 输入/输出操作失败 |
131.with上下文管理
finally 块由于是否发生异常都会执行,通常我们放释放资源的代码。其实,我们可以通过 with 上下文管理,更方便的实现释放资源的操作。
with 上下文管理的语法结构如下:with context_expr [ as var]: 语句块
with 上下文管理可以自动管理资源,在 with 代码块执行完毕后自动还原进入该代码之前的现场或上下文。不论何种原因跳出 with 块,不论是否有异常,总能保证资源正常释放。极大的简化了工作,在文件操作、网络通信相关的场合非常常用。
with open("d:/bb.txt") as f:
for line in f:
print(line)
132.trackback模块的使用_异常写入日志文件
trackback模块的使用
import traceback
try:
print("step1")
num = 1/0
except:
traceback.print_exc()
Traceback (most recent call last):
File "/Users/zhucan/PycharmProjects/pythonProject1/mypy01.py", line 4, in <module>
num = 1/0
ZeroDivisionError: division by zero
step1
异常写入日志文件
import traceback
try:
print("step1")
num = 1/0
except:
with open("d:/a.log","a") as f:
traceback.print_exc(file=f)
133.自定义异常类_raise抛出异常
自定义异常类
程序开发中,有时候我们也需要自己定义异常类。自定义异常类一般都是运行时异常,通常继承 Exception 或其子类即可。命名一般以 Error、Exception 为后缀。
class AgeError(Exception):
def __init__(self,errorInfo):
Exception. __init__(self)
self.errorInfo = errorInfo
def __str__(self):
return str(self.errorInfo)+",年龄错误!应该在 1-150 之间"
if __name__ == "__main__":
age = int(input("输入一个年龄:"))
if age<1 or age>150:
raise AgeError(age)
else:
print("正常的年龄:",age)
134.pycharm的调试模式
进行调试的核心是设置断点。程序执行到断点时,暂时挂起,停止执行。就像看视频按下停止一样,我们可以详细的观看停止处的每一个细节。
断点
程序运行到此处,暂时挂起,停止执行。我们可以详细在此时观察程序的运行情况,方便做出进一步的判断。
1.设置断点
(1)在行号后面单击即可增加断点
(2)在行号后面单击即可增加断点
进入调试视图
我们通过如下三种方式都可以进入调试视图:
1.单击工具栏上的按钮:
2.右键单击编辑区,点击:debug ‘模块名’
3.快捷键:shift+F9
进入调试视图后,布局如下:
左侧为“浏览帧”:调试器列出断点处,当前线程正在运行的方法,每个方法对应一个“栈帧”。最上面的 是当前断点所处的方法。
变量值观察区:调试器列出了断点处所在方法相关的变量值。我们可以通过它,查看变量的值的变化,也可以通过 ,增加要观察的变量。
我们通过上图中的按钮进行调试操作,它们的含义如下:
中文名称 | 英文名称 | 图标和快捷键 | 说明 |
显示当前所有断点 | show Execution Point |
| |
单步调试: 遇到函数跳过 | step over |
| 若当前执行的是一个函数,则会把这个 函数当做整体一步执行完。不会进入这个函数内部 |
单步调试: 遇到函数进入 | step into |
| 若当前执行的是一个函数,则会进入这个函数内部 |
跳出函数 | step out |
| 当单步执行到子函数内时,用 step out 就可以执行完子函数余下部分,并返回到上一层函数 |
执行的光标处 | run to cursor |
| 一直执行,到光标处停止,用在循环内 部时,点击一次就执行一个循环 |