Python异常处理与日志记录实战指南
本文深入解析Python中的异常处理机制,通过具体代码示例展示如何利用try-except捕获并处理日志解析中的数组越界等异常,确保程序在遇到错误数据时不中断。同时介绍Python标准库logging模块的配置方法,包括设置日志等级、输出控制台及本地文件存储,帮助开发者建立完善的错误追踪与调试体系。
Python异常处理与日志处理概述
本文总结近期在Python编程中关于异常处理与日志处理的实践经验。异常处理是软件开发中至关重要的环节。由于作者早期主要使用C++,该语言并未强制要求使用try...catch结构,因此在初期编码时往往忽略此部分。直到接触Java后,发现许多场景必须显式添加try...catch模块,但当时仅依赖Eclipse的自动补全功能或直接在类声明中使用throws Exception来规避编译错误,并未深入理解其原理。
近期在编写Python代码时,注意到Python同样广泛使用try...catch结构。为了彻底解决这一认知盲区,作者进行了深入的思考与梳理。
Python异常处理机制
Python异常处理
Python的异常处理语法结构相对简洁,基本形式如下:
try:
...(可能出现异常的代码)
except ...(Python内置异常类或者自己实现的异常类) as e: (或者直接except:)
...(处理该异常的代码)
以往作者通常忽略异常处理,依赖控制台打印的报错行号来定位问题,随后手动排查逻辑错误。经过反思,这种做法存在两个主要缺陷:
任何未捕获的错误都会导致程序直接中断,且错误提示信息往往不够直观,导致排查错误的时间显著增加。
详细解释如下:
问题一:作者之所以长期忽略此问题,是因为过往编写的程序规模较小,即使发生异常导致中断,影响也有限。然而,若未来参与多人协作的大型模块开发,一旦某个模块抛出未捕获异常导致整个程序崩溃,后果将不堪设想。
问题二:为说明此问题,举例如下。假设需要处理一个日志文件,其内容大致如下:
Jul 16 03:27:01 node69 sced[22053]: Connection from
Jul 16 03:27:01 node69 sced[22053]: SSH: Server;Ltype
Jul 16 03:27:01 node69 sced[22053]: SSH: Server;Ltype
Jul 16 03:27:11 node69 sced[23417]: Connection from
Jul 16 03:27:11 node69 sced[23417]: Connection from
Jul 16 03:27:11 node69 sced[23417]: SSH: Server;Ltype
Jul 16 03:27:11 node69 sced[23417]: SSH: Server;Ltype
Jul 16 03:27:20 node69 sced[23454]: Connection from
Jul 16 03:27:20 node69 sced[23454]: Connection from
目标是提取每行字符串中的'sced'名称。直观上,使用Python一行代码即可实现:
s = line.split()[4].split('[')[0].strip(':')
该写法在数据规范时无误,但实际日志文件通常规模巨大(如百万行),且可能包含空行或截断的不完整行,例如:
Jul 16 03:27:01 node69 sced[22053]: SSH: Server;Ltype
(空行)
Jul 16 03:27:11 node69 sced[23417]: Connection from
Jul 16 03:27:11 node69 sced[23417]: Connection from
Jul 16 03:27:11 (只有一半的行)
Jul 16 03:27:11 node69 sced[23417]: SSH: Server;Ltype
在处理此类数据时,程序会抛出数组越界异常并立即中断。每次遇到此类问题,作者需手动分析报错行,若不清楚异常行的具体形态,排查耗时极长。更糟糕的是,解决一个问题后,若后续数据出现其他异常,仍需重复上述过程。若能一次性从头到尾处理数据,在遇到异常时打印该行信息且程序不中断,将极大提升效率。这正是异常处理语句的应用场景,代码如下:
with open(fileName, 'r',encoding = 'utf-8' ,errors='ignore') as f:
for line in f.readlines():
try:
s = line.split()[4]
s = s.split('[')[0].strip(':')
theDict[s] = 1 if theDict.get(s,-1) == -1 else theDict[s]+1 #先得到日志的程序名出现次数的字典
except:
logging.exception('文件--' + fileName+'--在解析句子--'+line+'--时出现异常') #exception代表打印时也会打印出系统错误提示语句
# raise
起初,由于不确定可能遇到的异常类型,代码中仅打印异常信息而不抛出(raise)。若希望遇到异常时停止处理后续数据,可取消raise的注释。作者认为,raise的作用类似于程序中的return语句。
作者的目标是运行一次代码,打印出所有无法处理的行。上述写法实现了这一功能,充分展示了异常处理语句的实用价值。
总结:
编程的本质是实现特定逻辑,但开发者无法穷尽所有边界情况。此时引入异常处理模块,将异常信息打印出来,有助于在出现异常时提取关键数据,进而优化程序逻辑。
Python日志处理最佳实践
日志处理
关于日志处理,作者最大的体会是以往编程时从未使用日志功能,仅依赖cout、System.out.println或print等控制台输出语句进行调试。近期因研究方向涉及日志处理,不得不深入探究其必要性。
以上述代码为例,在except块中使用logging.exception打印信息。在运行时,这与直接在控制台打印异常处理语句看似无异,但在后期运维中,日志具备两项关键附加功能:
可根据设定的日志等级筛选并打印相应的日志输出语句。
可将日志写入本地文件,便于后期回溯和查找错误。
import logging
logging.basicConfig(level=logging.DEBUG) #这句话没次第一次运行时生效,修改必须重启Console
通过日志等级控制,既能决定不同级别日志是否显示,又能指定日志存储位置。这使得开发者在无法现场调试时,仅凭日志记录即可掌握程序异常状况,极大提升了远程维护的便利性。
以上关于Python异常处理和日志处理方式的分享,旨在为读者提供参考,欢迎支持。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









