news 2026/3/29 19:34:25

【Python学习】基础学习(三):异常处理、调试和测试

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Python学习】基础学习(三):异常处理、调试和测试

Python学习全部目录:
【Python学习】基础学习(一):变量与运算、数据类型、函数、类、模块
【Python学习】基础学习(二):文件管理与I/O编程

【Python学习】基础学习(三):异常处理、调试和测试

    • 异常处理、调试和测试
      • 控制异常try-except
      • 调试器pdb
      • Unittest单元测试
      • 异常/警告名称列表

异常处理、调试和测试

控制异常try-except

即使自己的的代码没有错误,但是有时也难以避免潜在的错误,比如说物理环境出错,CPU资源不够,调用的服务失败。
在写代码的时候,考虑如何对捕捉潜在的错误,预先写好对于可能错误的处理。

  1. try-except
    比如处理文件时候,如果读写不存在的文件就会报错:
withopen('no_file.txt','r')asf:print(f.read())# FileNotFoundError: [Errno 2] No such file or directory: 'no_file.txt'

我们需要注意的就是表示异常类型的报错关键词FileNotFoundError,需要手动捕捉这个错误并且进行处理

try:withopen('no_file.txt','r')asf:print(f.read())exceptFileNotFoundErrorase:print(e)withopen('no_file.txt','w')asf:f.write('This is a file for test.')print('new file "no_file.txt" has been written.')

有时候程序执行某种功能会报多种不同的异常,如果异常的处理方案相同,可以在except中写多个异常种类,会按照正常的执行顺序, 一次检测异常,报出第一个遇到的异常:

dic={'name':'Bob','age':20}l=[1,2,3]try:male=dic['gender']l[3]=4except(KeyErrororIndexError)ase:print('ker or index error for: ',e)# ker or index error for: 'gender'
  1. try-except-except
    如果想让多种异常分开处理,就需要写两个except
try:v=dic['gender']l[3]=4exceptKeyErrorase:print('key error for:',e)dic['gender']='Female'exceptIndexErrorase:print('index error for:',e)l.append(4)print(dic)print(l)# key error for: 'gender'# {'name': 'Bob', 'age': 20, 'gender': 'Female'}# [1, 2, 3]
  1. try-except-else
    这个模式在except处理报错情况:
lis=[1,2,3]try:print(lis[3])exceptIndexErrorase:print(e)lis.append(4)print(lis[3])else:print('now is in else.')# list index out of range# 4

else处理没有报错的情况:

lis=[1,2,3,4]try:print(lis[3])exceptIndexErrorase:print(e)lis.append(4)print(lis[3])else:print('now is in else.')# 4# now is in else.
  1. try-except-finally
    不管有没有错误,都会执行到finally内容
    有报错:
lis=[1,2,3]try:print(lis[3])exceptIndexErrorase:print(e)lis.append(4)print(lis[3])finally:print('reach finally.')# list index out of range# 4# reach finally.

没有报错:

lis=[1,2,3,4]try:print(lis[3])exceptIndexErrorase:print(e)lis.append(4)print(lis[3])finally:print('reach finally.')# 4# reach finally.

主要用在不管有没有报错,都想让程序继续执行,不处理任何异常:

try:dd=ddddfinally:print('I know there is an error, just ignore it.')# I know there is an error, just ignore it.# NameError: name 'dddd' is not defined
  1. 记录错误
    使用python内置的logging模块,就可以记录并打印输出错误信息,同时可以让程序继续执行,而不是出错就退出执行:
importlogging lis=[1,2,3]deflogerror():try:print(lis[3])exceptExceptionase:# Exception是基类logging.exception(e)logerror()print('main')# IndexError: list index out of range# main
  1. raise手动触发异常
    主动抛出异常,在错误的地方中断程序并输出清晰地错误信息
defno_negative(num):ifnum<0:raiseValueError('No Negative!')returnnum no_negative(-1)# Traceback (most recent call last):# ValueError: No Negative!

这种raise的用法,更常用在网络请求、读取数据库时,如果有raise写入到log中就会非常清晰易懂。

总结:做一个小练习

# 运行下面的代码,根据异常信息进行分析,定位出错误源头,并修复:fromfunctoolsimportreducedefstr2num(s):returnint(s)defcalc(exp):ss=exp.split('+')ns=map(str2num,ss)returnreduce(lambdaacc,x:acc+x,ns)defmain():r=calc('100 + 200 + 345')print('100 + 200 + 345 =',r)r=calc('99 + 88 + 7.6')print('99 + 88 + 7.6 =',r)main()# 100 + 200 + 345 = 645# Traceback (most recent call last):# File "/home/bupt/python/python_basic.py", line 17, in <module># main()# File "/home/python/python_basic.py", line 14, in main# r = calc('99 + 88 + 7.6')# File "/home/python/python_basic.py", line 9, in calc# return reduce(lambda acc, x: acc + x, ns)# File "/home/python/python_basic.py", line 4, in str2num# return int(s)# ValueError: invalid literal for int() with base 10: ' 7.6'

从上往下分析错误信息,最后发现是str2num(s)函数调用的int(s)出错,不能转换7.6这个浮点数

调试器pdb

(以下为不依赖IDE的调试方式)

启动python的调试器pdb,让程序以单步方式运行,可以随时查看运行状态:

s='0'n=int(s)print(10/n)

配置参数-m pdb命令行执行python程序:
python -m pdb python_basic.py
使用n单步执行,使用p 变量名查看变量的值

>/home/python/python_basic.py(1)<module>()->s='0'(Pdb)(Pdb)n# 使用 n 单步执行>/home/python/python_basic.py(2)<module>()->n=int(s)(Pdb)n>/home/python/python_basic.py(3)<module>()->print(10/ n)(Pdb)p s# 使用 p 查看变量'0'(Pdb)n ZeroDivisionError: division by zero>/home/python/python_basic.py(3)<module>()->print(10/ n)(Pdb)n --Return--

可以import pdb,使用pdb.trace()设置断点:

importpdb s='0'n=int(s)pdb.set_trace()print(10/n)

使用python python_basic.py运行程序,会自动在断点处暂停进入pdb调试环境,使用命令p查看变量,使用命令c继续运行:

$ python python_basic.py>/home/bupt/python/python_basic.py(5)<module>()->pdb.set_trace()(Pdb)p s'0'(Pdb)p n0(Pdb)c Traceback(most recent call last): File"/home/bupt/python/python_basic.py", line6,in<module>print(10/ n)~~~^~~ ZeroDivisionError: division by zero

Unittest单元测试

运行整套程序,检查哪里出错的测试方法只适合:小型项目/项目功能之间关联少的少量功能项目,否则,使用单元测试是更好的测试方法。

单元测试就是不直接测试全套程序逻辑,而是将小功能模块拆开逐个测试。在Python中,常用unittest测试框架做单元测试。

在class中继承unittest.TestCase,编写函数,以test开头的TestXxx类被认为是测试类,test_xxx方法被认为是测试方法
__main__函数中执行unittest.main(),这个“测试运行器”会自动发现并执行定义的测试类中所有的测试方法:

importunittestclassTestFunc(unittest.TestCase):deftest_example(self):self.assertEqual(2,divide(2,1))self.assertEqual(2,divide(-2,-1))# self.assertEqual(-1, divide(-2, 0))defdivide(a,b):returna/bif__name__=='__main__':unittest.main()# .# --------------------# Ran 1 test in 0.000s# OK

如果测试不通过,会报错:

self.assertEqual(-1,divide(-2,0))# return a / b# ~~^~~# ZeroDivisionError: division by zero# ---------------------------------------------------------------------# Ran 1 test in 0.000s# FAILED (errors=1)
  1. unittest规范
    可以先写unittest,然后再开发功能,类似于先设立目标,然后实现目标:
    比如想要:输入 1 返回 2,输入 -1 返回 3,输入其他任何数,返回 1。可以像下面一样先把test_func部分写好:
classTestFunc(unittest.TestCase):deftest_example(self):# 期望实现的功能self.assertEqual(2,my_func(1))self.assertEqual(3,my_func(-1))foriinrange(-100,100):ifi==1ori==-1:continueself.assertEqual(1,my_func(i))defmy_func(num):if__name__=='__main__':unittest.main()

测试文件要与原本的功能文件分开,测试文件以_test.py结尾,引入from all_my_func import my_func功能模块函数以进行测试,
可以同时测试多个功能模块:

defmy_func1(a):ifa==1:return2elifa==-1:return3else:return1defmy_func2(letter):ifletter=='yes':returnTrueelse:raiseValueError("Only YES!")classTestFunc(unittest.TestCase):deftest_func1(self):self.assertEqual(2,my_func1(1))self.assertEqual(3,my_func1(-1))foriinrange(-100,100):ifi==1ori==-1:continueself.assertEqual(1,my_func1(i))deftest_func2(self):self.assertTrue(my_func2('yes'))withself.assertRaises(ValueError):# 报错才能通过testmy_func2("nononono")if__name__=="__main__":unittest.main()# ..# ----------------------------------------------------------------------# Ran 2 tests in 0.000s# OK

通常将测试代码写在test.py文件中,在命令行使用python指令执行测试:
python -m unittest test.py

如果写出了很多的功能测试,但有时只想执行某一个test,可以进行如下替换:
但是这样写灵活性太差:

# unittest.main()suite=unittest.TestSuite()suite.addTest(TestFunc('test_func1'))unittest.TextTestRunner.run(suite)# .# ----------------------------------------------------------------------# Ran 1 test in 0.000s# OK

不如直接命令行执行对应参数命令来执行不同的test,灵活性更强:
python -m unittest testmodule.testclass.test_method

  1. setUp()&tearDown()
    在使用unittest进行单元测试时,可能需要前置准备后置清理
    -> 测试前需要准备数据,连接数据库,打开文件;
    -> 测试后需要清理数据,关闭数据库连接,删除临时文件
    为了避免在每一个测试方法中重复写这些准备和清理的代码,unittest提供了两个钩子方法:
  • setUp()
    在每个测试方法运行之前都会被自动调用
    用于创建测试所需要的环境或数据准备
  • tearDown()
    在每个测试方法运行之后都是被自动调用
    用于释放资源,清楚测试过程中产生的数据或恢复环境状态
importunittestclassTestExample(unittest.TestCase):defsetUp(self):print('setUp')returnsuper().setUp()deftearDown(self):print('tearDown')returnsuper().tearDown()deftest_fun1(self):print('test func 1')self.assertTrue(True)deftest_fun2(self):print('test func 2')self.assertEqual(1+1,2)if__name__=='__main__':unittest.main()# setUp# test func 1# tearDown# .setUp# test func 2# tearDown# .# ------------------------------------------# Ran 2 tests in 0.000s# OK

数据库连接场景:

defsetUp(self):self.conn=db.connect()self.cursor=self.conn.cursor()deftearDown(self):self.cursor.close()self.conn.close()

临时文件创建与删除:

defsetUp(self):self.file=open('temp.txt','w')deftearDown(self):self.file.close()os.remove('temp.txt')
  1. unittest断言方法列表
断言方法含义
assertEqual(a, b)判断a == b
assertNotEqual(a, b)判断a != b
assertTrue(condition)判断condition 是 True
assertFalse(condition)判断condition 是 False
assertGreater(a, b)判断a > b
assertGreaterEqual(a, b)判断a >= b
assertLess(a, b)判断a < b
assertLessEqual(a, b)判断a <= b
assertIs(a, b)判断a is b(是否是同一个对象
assertIsNot(a, b)判断a is not b(不是同一个对象)
assertIsNone(a)判断a is None
assertIsNotNone(a)判断a is not None
assertIn(a, b)判断a in b(a 是否在 b 中)
assertNotIn(a, b)判断a not in b(a 不在 b 中)
assertRaises(error)判断是否抛出了指定的异常(常与with一起使用)

异常/警告名称列表

异常名称描述
BaseException所有异常的基类
SystemExit解释器请求退出
KeyboardInterrupt用户中断执行(通常是 Ctrl+C)
Exception常规错误的基类
StopIteration迭代器没有更多的值
GeneratorExit生成器(generator)发生异常来通知退出
StandardError(Python 3 中已移除)所有内建标准异常的基类
ArithmeticError所有数值计算错误的基类
FloatingPointError浮点计算错误
OverflowError数值运算超出最大限制
ZeroDivisionError除以零或取模为零(适用于所有数据类型)
AssertionError断言语句失败
AttributeError对象没有该属性
EOFError没有内建输入,到达 EOF 标记
EnvironmentError(已合并进 OSError)操作系统错误的基类
IOError(Python 3中与 OSError 合并)输入/输出操作失败
OSError操作系统错误
WindowsError(仅限 Windows,Python 3 已移除)系统调用失败
ImportError导入模块/对象失败
LookupError无效数据查询的基类
IndexError序列中没有此索引
KeyError映射中没有这个键
MemoryError内存溢出错误(不是致命错误)
NameError未声明或未初始化的对象(变量不存在)
UnboundLocalError访问未初始化的本地变量
ReferenceError弱引用(weakref)试图访问已被回收的对象
RuntimeError一般的运行时错误
NotImplementedError尚未实现的方法
SyntaxErrorPython 语法错误
IndentationError缩进错误
TabErrorTab 与空格混用导致缩进错误
SystemError解释器系统错误
TypeError对类型无效的操作
ValueError传入无效参数(类型对但值不对)
UnicodeErrorUnicode 相关错误的基类
UnicodeDecodeErrorUnicode 解码错误
UnicodeEncodeErrorUnicode 编码错误
UnicodeTranslateErrorUnicode 转换错误
警告名称描述
Warning警告的基类
DeprecationWarning关于被弃用特性的警告
PendingDeprecationWarning将来某个版本会弃用的特性警告
FutureWarning构造将来语义可能会改变的警告
RuntimeWarning可疑的运行时行为警告
SyntaxWarning可疑的语法警告
UserWarning用户代码生成的警告
OverflowWarning(Python 2 使用,Python 3 已移除)自动转为 long 类型的旧警告
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/27 17:39:13

论文生成源码排名:9大平台+开源开发工具

论文生成源码排名&#xff1a;9大平台开源开发工具 核心工具对比速览 工具名称 核心功能 处理时间 适配检测系统 特色优势 aibiye 论文降重与AIGC优化 15-30分钟 知网/维普/万方 语义级改写技术&#xff0c;保留学术逻辑 aicheck AIGC检测与降重 20分钟 知网/格子…

作者头像 李华
网站建设 2026/3/27 2:22:58

打造个人专属媒体王国:Jellyfin跨平台一键部署全攻略

还在为手机、电脑、电视上的媒体文件分散管理而头疼吗&#xff1f;想要随时随地欣赏自己的电影收藏却苦于找不到合适的解决方案&#xff1f;今天我要向你推荐一款完全免费、功能强大的个人媒体服务器软件——Jellyfin&#xff0c;让你轻松拥有属于自己的媒体王国&#xff01; 【…

作者头像 李华
网站建设 2026/3/26 9:52:10

文科通讯作者工具:8大平台+规范查询排名

文科通讯作者工具&#xff1a;8大平台规范查询排名 文科通讯作者工具&#xff1a;8大平台规范查询排名 核心工具对比速览 工具名称 核心功能 适用场景 效率评分 特色优势 aibiye 论文选题与框架生成 文科开题报告/文献综述 ★★★★☆ 文科专业适配度高 aicheck 开…

作者头像 李华
网站建设 2026/3/28 11:32:19

深蓝词库转换:跨平台输入法词库迁移终极指南

深蓝词库转换&#xff1a;跨平台输入法词库迁移终极指南 【免费下载链接】imewlconverter ”深蓝词库转换“ 一款开源免费的输入法词库转换程序 项目地址: https://gitcode.com/gh_mirrors/im/imewlconverter 你是否曾经因为更换输入法而苦恼于词库无法迁移&#xff1f;…

作者头像 李华
网站建设 2026/3/27 11:31:17

离线安装.net3.5 sp

把提取的SXS放在C盘根目录&#xff0c;在管理员模式下powershell或者cmd复制下面脚本直接运行。 把sxs文件夹放到C盘根目录了&#xff0c;那么直接用如下代码即可 dism.exe /online /enable-feature /featurename:netfx3 /Source:C:\sxs 源网址在&#xff1a; 源网址在 Win10…

作者头像 李华
网站建设 2026/3/27 3:29:13

获奖名单来啦!Vibe Coze AI 挑战赛 -企业 AI 应用赛道圆满收官!

&#x1f4e3;经过激烈角逐&#xff0c;最终获奖结果正式揭晓&#xff01;感谢所有参赛者的精彩表现&#xff0c;也恭喜这些团队/个人突出重围&#xff0c;所有方案均聚焦企业真实痛点&#xff0c;用AI技术切实降低运营成本、提升决策效率&#xff0c;展现了AI赋能企业的实用价…

作者头像 李华