13. 如果自己写的 Python 程序出错了,怎么办?

梦想橡皮擦 等级 341 1 0

本篇文章主要内容为程序错误与异常处理,顺带会说一下内置模块 logging 。

缓解一下视疲劳

13. 如果自己写的 Python 程序出错了,怎么办?

缓解一下视疲劳

十三、Python 程序异常处理与 logging 模块

13.1 程序异常

程序异常,就是程序出错了,程序员一般叫做 BUG(八哥),写程序不出错是不可能发生的事情,而程序员要做的事情就是及时的捕获错误,修改错误。

13.1.1 最常见的错误 - 除数为 0

在数学中也存在类似的问题,除数不可以为 0。相同的概念在编程中也是存在的。

num1 = 20
num2 = 0
num3 = num1 / num2
print(num3)

运行代码出现下面的错误:

Traceback (most recent call last):
  File "D:/gun/2/demo7.py", line 3, in <module>
    num3 = num1 / num2
ZeroDivisionError: division by zero

错误内容就是末尾的 ZeroDivisionError: division by zero ,当出现错误程序崩溃,终止运行。错误异常中也提示了错误出现的行数 line 3 在第三行,但查看行号排查错误在很多时候无法直接解决问题,因为出错的地方不在行号那一行,修改 BUG 的效率一般会随着你对 Python 学习的深入逐步增强改善。

13.1.2 try ... except 语句

刚才的程序出现错误就终止运行了,如何避免程序被强迫终止,出现问题提示出问题,然后继续运行呢?这就是 try ... except 语句使用的场景了。

语法格式:

try:
    可能会出错的代码
except 异常对象:
    处理异常代码

按照上述语法格式修改上文代码。

num1 = 20
num2 = 0
try:
    num3 = num1 / num2
except ZeroDivisionError:
    print("除数不可以为 0 ")

此时程序不会报错,当发现除数为 0 会进入异常处理,直接输出除数不能为 0。

try 表示测试代码部分是否存在异常,except 表示捕获异常,前提是出现异常。如果 try 语句中没有任何错误,except 中的代码不会执行。

还有一点需要注意,在 except 后面是异常对象,该异常对象我们设置为 ZeroDivisionError 这是因为已经知道是会出现这个异常,如果在编码过程中不知道会出现哪种异常,依旧会出现错误。

num1 = 20
num2 = "abc"
try:
    num3 = num1 / num2
except ZeroDivisionError:
    print("除数不可以为 0 ")

上述代码依旧会报错,报错的异常为:

Traceback (most recent call last):
  File "D:/gun/2/demo7.py", line 4, in <module>
    num3 = num1 / num2
TypeError: unsupported operand type(s) for /: 'int' and 'str'

如果想在 except 后面支持本异常,需要添加上 TypeError

num1 = 20
num2 = "abc"
try:
    num3 = num1 / num2
except (ZeroDivisionError,TypeError):
    print("除数不可以为 0 ")

也可以分开编写:

num1 = 20
num2 = "abc"
try:
    num3 = num1 / num2
except ZeroDivisionError:
    print("除数不可以为 0 ")

except TypeError:
    print("除数类型不对")

该种写法在书写的时候需要预先知道会提示哪种异常,如果异常不清楚那可以省略异常对象,直接使用下述代码即可。

num1 = 20
num2 = "abc"
try:
    num3 = num1 / num2
except:
    print("除数不可以为 0 ")

13.1.3 try ... except ... else 语句

在 try ... except 语句后面可以增加一个 else 语句,该语句表示的含义可以按照如下描述进行理解,当出现异常的时候执行 except 语句中的代码,当无异常执行 else 语句代码。

num1 = 20
num2 = 1
try:
    num3 = num1 / num2
except ZeroDivisionError:
    print("除数不可以为 0 ")

except TypeError:
    print("除数类型不对")

else:
    print("无异常,会被执行")

以上代码无错误,那 else 语句就会被执行到。

13.2 异常类型

13.2.1 常见的异常类型

在编写代码的过程中,你需要掌握一些常见的异常类型,熟记它们可以帮助你快速进行错误排查。

  • AttributeError 某个对象没有属性
  • Exception 通用型异常对象
  • FileNotFoundError 找不到文件
  • IOError 输入输出异常
  • IndexError 索引异常
  • KeyError 键异常
  • NameError 对象名称异常
  • SyntaxError 语法错误
  • TypeError 类型错误
  • ValueError 值错误

以上错误都属于常见错误,其中重点以 Exception 通用异常对象与 SyntaxError 语法错误为主,它们两个是最常出现的。

很多时候其实直接使用通用异常对象 Exception 就可以了,不需要记住所有的异常类型的。

13.2.2 捕捉多个异常

在上文已经接触过捕捉多个异常的语法格式了,可以在学习一下。

try:
    可能出错的代码块
except 异常对象1:
    异常处理代码块
except 异常对象2:
    异常处理代码块

13.2.3 一个 except 捕获多个异常

Python 也支持使用一个 except 捕获多个异常,具体语法格式如下:

try:
    可能出错的代码块
except (异常对象1,异常对象2...):
    异常处理代码块

13.2.4 直接抛出异常

捕获到异常之后,可以直接抛出 Python 给内置好的异常信息,例如:

num1 = 20
num2 = 0
try:
    num3 = num1 / num2
except ZeroDivisionError as e:
    print(e)

except TypeError as e:
    print(e)

else:
    print("无异常,会被执行")

注意 except 后面异常对象使用 as 关键字起了一个别名叫做 e,然后直接输出 e 就是 Python 内置好的错误信息了。这里的 e 可以为任意名称,遵循变量命名规则即可。

13.3 finally 语句

try ... except 语句还可以和 finally 语句配合,形成下述语法格式:

try:
    可能出错的代码块
except:
    代码出错执行的代码块
else:
    代码正常执行的代码块
finally:
    无论代码是否有异常出现都会执行的的代码块

finally 语法需要与 try 语句配合使用,无论是否有异常出现都会执行该语句内容,具体代码大家可以自行测试即可。

13.4 日志模块 logging

13.4.1 logging 模块

在 Python 中为了更好的记录程序错误信息,提供了一个 logging 模块供我们使用,该模块提供了 5 个等级用于标记日志信息的等级。

  1. DEBUG 等级,使用 logging.debug() 显示
  2. INFO 等级,记录类的日志
  3. WARNING 等级,警告级别,存在潜在风险
  4. ERROR 等级,引发错误
  5. CRITICAL 等级,引发系统出现问题,最高等级

导入 logging 模块之后,可以使用下述内容设置显示信息的等级。

import logging
logging.basicConfig(level=logging.DEBUG)

五个等级输出函数如下:

import logging
logging.basicConfig(level=logging.DEBUG)

logging.debug("DEBUG")
logging.info("INFO")
logging.warning("WARNING")
logging.error("ERROR")
logging.critical("CRITICAL")

输出内容如下:

DEBUG:root:DEBUG
INFO:root:INFO
WARNING:root:WARNING
ERROR:root:ERROR
CRITICAL:root:CRITICAL

上述代码因为设置的等级是 DEBUG,所以所有的日志信息都会输出,如果设置为 WARNING,例如下述代码,查看输出内容。

import logging
# 注意看这里的设置
logging.basicConfig(level=logging.WARNING)

logging.debug("DEBUG")
logging.info("INFO")
logging.warning("WARNING")
logging.error("ERROR")
logging.critical("CRITICAL")

因为设置了 logging 输出等级是 WARNING,所以较低等级的 DEBUG 与 INFO 将不再输出,这样可以随着程序开发不断的提高等级,最终提高到 CRITICAL。

13.4.2 格式化 logging 日志信息

可以在全局进行 logging 信息的格式化,语法格式如下:

logging.basicConfig(level=logging.WARNING,format = "")

在不设置 format 的时候,默认输出的日志信息如下,所以输出内容前面都存在一个 DEBUG:root: 内容,如果设置 format="" 即可删除原内容。

DEBUG:root:DEBUG
INFO:root:INFO
WARNING:root:WARNING
ERROR:root:ERROR
CRITICAL:root:CRITICAL

设置 format = "",代码如下:

import logging
logging.basicConfig(level=logging.WARNING,format= "")

其余内容不需要修改,输出的日志信息,已经没有前面的默认关键词了。

WARNING
ERROR
CRITICAL

对于日志信息的格式化,还可以增加 asctime ,该内容为时间信息,例如下述代码:

import logging
logging.basicConfig(level=logging.WARNING,format= "%(asctime)s")

logging.debug("DEBUG")
logging.info("INFO")
logging.warning("WARNING")
logging.error("ERROR")
logging.critical("CRITICAL")

使用该内容运行结果发现,要输出的信息没有了,这是因为你在 format 参数中只传了 asctime 一个内容,如果还需要 logging 输出信息,需要增加 message,语法如下:

import logging
logging.basicConfig(level=logging.WARNING,format= "%(asctime)s %(message)s")

logging.warning("WARNING")
logging.error("ERROR")
logging.critical("CRITICAL")

学习过 asctimemessage 之后,你应该对 format 格式化的语法有了一些基本的认知,它应该是一个 %(参数名)s 这样的结构,如果增加一个 logging 等级参数 levelname,尝试一下你可以将其拼接到 format 中吗?

13.4.3 程序日志 logging 输出到文件中

程序日志如果都输出在 Python 控制台,导致的结果就是控制台出现大量的调试信息,很多时候可以将日志信息输出到文件中,而且实现非常简单,只需要增加一个参数 filename 即可解决问题。

import logging
logging.basicConfig(filename = "out.txt",level=logging.WARNING,format= "%(asctime)s %(message)s")

执行上述代码之后,会自动在当前根目录(文件与目录可以自己设置)生成一个日志文件。

13.4.4 停用程序日志

使用下述方法停用日志。

logging.disable(level)

如果希望全部停用,只需要直接限制等级到 CRITICAL 即可。

import logging
logging.basicConfig(level=logging.WARNING,format= "%(asctime)s %(message)s")
logging.disable(level=logging.CRITICAL)
logging.debug("DEBUG")
logging.info("INFO")
logging.warning("WARNING")
logging.error("ERROR")
logging.critical("CRITICAL")

13.5 这篇博客的总结

本篇博客主要写的是异常相关知识,在 Python 代码的编写过程中经常会出现异常,一般情况下程序员都叫做 出 BUG 了,这个 BUG 就是臭虫的意思,表示程序出臭虫了。当然很多时候我们也戏称“无 BUG,不编程”。

发现 BUG,解决 BUG,程序员不是在写 BUG 的路上,就是在改 BUG 的路上,好友哲理。

关于异常部分,还有如下内容可以扩展。

  • 使用 raise 抛出异常
  • 使用 traceback 模块记录异常信息到文件中
  • 程序断言 assert

🈚🈚🈚🈚🈚


博主 ID:梦想橡皮擦,希望大家点赞评论收藏

收藏
评论区

相关推荐

1. 这才是 Python 学习的正确起手姿势,滚雪球学 Python
在博客上,我写了很多关于 Python 的文章,很多朋友可能觉得橡皮擦应该是一个 Python 开发人员或者一个技术开发人员,但很遗憾的告诉大家,橡皮擦恰好是很多公司中开发人员的对立面【产品经理】。但我是一个相当懂技术人的产品经理。 一、Python 初次接触,Python 变量与基本运算 1.1 滚雪球学 Python 课程前置导语 从本篇博
5. Python 循环的本质就是一段代码懒得重复写
为啥要滚雪球学 Python,目的就是当你学会编程一些思想之后,可以让知识的雪球自行滚动起来。 五、Python 循环的本质就是一段代码懒得重复写 程序中的循环概念非常容易理解,一段相似的代码不想重复去写,然后让程序去完成这个操作就是循环。例如从 1 加到 100,如果你依次去加会发现,代码又臭又长,最好的写法当然是让程序通过循环依次去累加。
11. 用别人写好的代码,完成我的工作,剩下的时间去摸鱼
今天是持续写作的第 <font color"red"11</font / 100 天。 如果你有想要交流的想法、技术,欢迎在评论区留言。 Python 为何那么多人都喜欢,就是因为很多大佬给我们造好了“轮子”了,拿着大佬的轮子,我骄傲 十一、Python 模块的设计与应用 模块是一个概念,它包含 1N 个文件,如果文件是 Python 代码
12. 数据放在本地,心里才更踏实,滚雪球学 Python
今天是持续写作的第 <font color"red"12</font / 100 天。 如果你有想要交流的想法、技术,欢迎在评论区留言。 本篇文章要讲解的内容是 Python 文件操作的相关内容,滚雪球学 Python 第一遍已经进行到中途,是否还能坚持住呢?加油。 十二、Python 文件读取与写入 电脑文件的操作是任何一门编程语言都会涉
13. 如果自己写的 Python 程序出错了,怎么办?
本篇文章主要内容为程序错误与异常处理,顺带会说一下内置模块 logging 。 <center<font colorred缓解一下视疲劳</font</center 13. 如果自己写的 Python 程序出错了,怎么办?(https://imghelloworld.osscnbeijing.aliyuncs.com/ee1f42d25d
14. Python 与数据库那点事儿,滚雪球学 Python
本篇文章将给大家介绍 Python 如何操作 SQLite 数据库,本文将是滚雪球学 Python 第一阶段的倒数第二篇文章。 <center<font color
15. Python 程序运行速度如何提高十倍?第一遍滚雪球学 Python 收工
本篇文章将给大家介绍 Python 多线程与多进程相关知识,学习完该知识点之后,你的 Python 程序将进入另一个高峰。 <center<font colorred缓解一下视疲劳</font</center 15. Python 程序运行速度如何提高十倍?第一遍滚雪球学 Python 收工(https://imghelloworld.oss
易班自动刷网薪系统
写在前面 Python 课最后的大作业,跟大哥们一起写这个小玩意,因为学院好像很喜欢刷这些东西,总体来说挺简单的 分到我的模块刚刚好需要手机抓包,网页端易班登陆进去没有发动态的模块了,模块在维护 后续会更新其他人的板块并尝试做出来真正的模拟登陆(逆向app或者使用appium提取loginToken) 源码python coding: utf8 """@T
关于学习python的一点意见分享
Python适合初学者入门。Python作为一门叫做ABC语言的替代品。 Python提供了高效的高级数据结构,还能简单有效地面向对象编程。相比其他主流语言,有更好的可读性,上手相对容易。各种模块,免去了很多重复的工作,更快地写出东西。配置环境也不复杂,mac和linux内置了Python。自学python,最大的3个经验:.一本易懂,比较好的教程,从头到尾
你写的Python代码规范吗?
总第141篇/张俊红1.什么是PEP8PEP 是 Python Enhancement Proposals 的缩写,直译过来就是「Python增强建议书」也可叫做「Python改进建议书」,说的直白点就是Python相关的一些文档,主要用来传递某些信息,这些信息包括某个通知亦或是某个新的规范。关于更深层次的概念,大家有兴趣的可以自行去了解。PEP 后面的数字
这些常见的坑,90%的程序猿都踩过,来看看里面有没有你的脚印?
在学习python的过程中,相信大家都有踩过不少的坑,有些坑可能踩了不止一次,感觉就像是在坑与坑之间反复横跳。那么如何避免这些坑呢?看完这篇文章,你就知道了。我们来谈谈我们学习python的过程中,最常见的七大坑:1. 缩进,符号和空格不正确写代码时大家会使用缩进、对齐、空格等,这些是为了提高代码的可读性在python语言中,缩进是十分重要的比如在创建一个新
Python 为什么没有 main 函数?为什么我不推荐写 main 函数?
毫无疑问 Python 中没有所谓的 main 入口函数,但是网上经常看到一些文章提“Python 的 main 函数”、“建议写 main 函数”……有些人是知情的,他的意图可能是模仿那些正宗的 main 函数,但还有不少人明显是被误导了(或自己误解了),就写出来很累赘的代码。本期“Python 为什么”栏目来聊聊 Python 为什么没有 main 函数
Python 为什么没有 main 函数?为什么我不推荐写 main 函数?
毫无疑问 Python 中没有所谓的 main 入口函数,但是网上经常看到一些文章提“Python 的 main 函数”、“建议写 main 函数”……有些人是知情的,他的意图可能是模仿那些正宗的 main 函数,但还有不少人明显是被误导了(或自己误解了),就写出来很累赘的代码。本期“Python 为什么”栏目来聊聊 Python 为什么没有 main 函数
用Python写几行代码,一分钟搞定一天工作量,同事直呼:好家伙!
前几天有一个读者说最近要整理几千份文件,头都要整秃了,不知道能不能用Python解决,我们来看一下,你也可以思考一下。 由于涉及文件私密所以具体内容已做脱敏处理。大概是这样,一个文件夹下有多份会议通知信息(本文以 7 份文件为例)每一份通知打开格式基本类似,如下所示👇现在需要将每份会议文档中的 学习时间、学习内容、学习形式、主持人 四项关键信息提取出来,整理
25条很棒的Python一行代码,建议收藏!
自从我用Python编写第一行代码以来,就被它的简单性、出色的可读性和特别流行的一行代码所吸引。 在下面,我将给大家介绍并解释一些Python一行程序。 可能有些你还不知道,但对你未来的Python项目很有用。 ▍1、交换两个变量  a  4 b  5 a,b  b,a  print(a,b)  5,4 让我们通过交换两个变量作为一个简