七、异常处理
语法错误不属于异常,处理的是程序运行时的一些意外情况
代码:
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 123finally:print("我是Finally")r = func()
print(r)
结果:
我是Finally
123
在try里面的return不会打断finally的运行,但如果return在try之前,那么函数终止,不会运行try
八、traceback模块
try-execept提供的信息量太少,需要借助traceback
代码:
import tracebacktry: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系统')