Python个人学习笔记(18):模块(异常处理、traceback、日志记录)

发布于:2025-03-20 ⋅ 阅读:(19) ⋅ 点赞:(0)

七、异常处理

语法错误不属于异常,处理的是程序运行时的一些意外情况
代码:

a = int(input('>>>:'))
b = int(input('>>>:'))
print(a / b) # 在运行的时候由于数据不对,导致出错
# 此时程序会中断
print('我要上天')

结果:
Traceback (most recent call last):
File “D:\PycharmProjects\樵夫老师Python零基础课程\4_模块\39_python的异常处理.py”, line 3, in
print(a / b)
^
ZeroDivisionError: division by zero

如果异常不处理,那么程序会中断
语法:
try:
xxx
except 类型 as 变量:
xxxxx
except 类型 as 变量:
xxxxx

else:
xxxx
finally:
xxxx

尝试运行一段代码,如果不出错,就正常结束,如果出错,自动运行except内容
代码:

a = int(input('>>>:'))
b = int(input('>>>:'))
try:
    print(a / b)
except:
    print("出错了。。。")

print('我要上天')

结果:

>>>10
>>>2
5.0
我要上天
>>>10
>>>0
出错了。。。
我要上天

不打断程序的后续运行
在except中需要错误信息
在try中收集错误信息,然后传递给except
语法:except Exception as e:
exception:错误类型
e:错误信息的接受变量

代码:

a = int(input('>>>:'))
b = int(input('>>>:'))
try:
    print(a / b)
except ZeroDivisionError as e:
    print("出错了。。。", e)

print('我要上天')

结果:

>>>10
>>>0
出错了。。。 division by zero
我要上天

根据可能发生的问题,可以分列多个except

try:
    a = int(input('>>>:'))
    b = int(input('>>>:'))
    print(a / b)
except ZeroDivisionError as e:
    print("小错误", e)
except TypeError as e:
    print("中错误", e)
except Exception as e:
    print("大错误", e)
else: # 不出错走else,基本用不上
	pass
finally: #最终收尾,无论报不报错,比如数据库操作完毕后都需要关闭链接
    print("最终收尾")

print('我要上天')

exception可以接收其他错误

实际应用中,不会写的像上面那么复杂,最多为下面的结构

try:
	pass # 程序内容
except Exception as e:
	pass
finally:
	pass

在函数中使用try
代码:

def func():
    try:
        print(1/0)
    except Exception as e:
        return 123
    finally:
        print("我是Finally")

r = func()
print(r)

结果:

我是Finally
123

在try里面的return不会打断finally的运行,但如果return在try之前,那么函数终止,不会运行try

八、traceback模块

try-execept提供的信息量太少,需要借助traceback
代码:

import traceback

try:
    print(1/0)
except Exception as e:
    print(traceback.format_exc())

结果:
Traceback (most recent call last):
File “D:\PycharmProjects\樵夫老师Python零基础课程\4_模块\40_traceback.py”, line 4, in
print(1/0)
^
ZeroDivisionError: division by zero

结果显示调用栈(错误信息),但字体不是红色的
代码调试期间用try-except-traceback,上线后不要留

九、logging模块:日志记录

代码不用记,是固定的,不需要自己手动写

import logging

# 基础配置
logging.basicConfig(filename='x1.txt', # 文件名
                    format='%(asctime)s-%(name)s-%(levelname)s -%(module)s:NBSP %(message)s',
                    # 日志的格式:时间、日志名字、错误级别、模块、事件
                    datefmt='%Y-%m-%d %H:%M:%S', # 时间格式
                    level=30) # 被记录日志中的错误等级,只有level≥30的信息会被记录

当前配置表示 10以上的分数会被写入文件
logging模块自动划分了一些日志等级
logging.CRITICAL:最高级别错误,50
logging.ERROR:普通错误,40
logging.WARNING:警告,30
logging.INFO:信息,20
logging.DEBUG:最详细,10

代码:

logging.error("我上天了") # level=40
logging.info("我感冒了") # level=20

结果:
在这里插入图片描述
设置的级别为30及以上,因此info的信息没有记录进去
项目上线之前,可以把level降很低,把所有日志信息都记录下来,上线之后把level调高,减少日志信息

logging.log(18,“我想上厕所”):自行设置一个18级的信息,不推荐

完整的错误处理逻辑:
代码:

import traceback
try:
    print(1/0)
except Exception as e:
    logging.error(traceback.format_exc())

结果:
在这里插入图片描述
自动记下了错误的信息

如果项目极其庞大,可以考虑设置多个日志
代码:

#配置一个操作日志的对象logger(依赖FileHandler)
file_handler = logging.FileHandler('11.log','a',encoding='utf-8') # 避免乱码
file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s -%(name)s-%(levelname)s -%(module)s: %(message)s"))

logger1 = logging.Logger('s1',level=logging.ERROR)
logger1.addHandler(file_handler)

logger1.error('我是A系统')

#再设置一个操作日志的对象logger(依赖FileHandler)
file_handler2 = logging.FileHandler('12.log','a', encoding='utf-8')
file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s -%(name)s -%(levelname)s -%(module)s:%(message)s"))

logger2 =logging.Logger('s2',level=logging.ERROR)
logger2.addHandler(file_handler2)

logger2.error('我是B系统')