一:logging模块
1.日志级别:
1.debug调试信息(用于记录程序员在开发过程中调试信息,例如:不清楚变量值,打印看一下)
2.info记录普通信息(没有特别意义,就是简单的记录)
3.warning警告信息(当某些操作可能发生错误时,就记录为警告信息,涉及一些敏感操作时,例如删库)
4.error错误信息(当程序遇到错误无法继续执行时,例如要求用户输入一个整数,输入的却是小数,导致类型转换失败)
5.critical严重错误(当程序遇到错误无法继续执行时,例如:需要一个核心组件,却被删了)
默认情况下:级别为warning,输出的位置为控制台,默认格式为:级别:日志生成器名称:调试的消息。
2.如果需要更加详细的去制定logging的各项功能,就需要系统的了解logging模块
四种核心角色:
Logger:日志生成器 负责产生一条完整的日志
Filter:过滤器 负责对日志进行过滤
Handler:处理器 负责将日志输出到指定格式(接收日志然后打印到不同的地方,FileHandler用来打印到文件中,StreamHandler用来打印到终端)
Formatter:格式化 负责处理日志的显示格式(可以控制不同的日志格式对象,然后绑定给不同的Handle对象使用,以此来控制不同的Handle的日志格式)
一条日志的生命周期:1.由logger产生日志
2.交给过滤器进行过滤
3.交给Handler按照Formater的格式进行输出
这三步都可以对日志进行筛选,什么样的需要显示,什么样的不需要显示
3.可以在logging.basicConfig()函数中通过具体的参数来更改logging模块的默认行为,可用参数有
filename:用指定的文件名创建FileHandler(后边会具体讲解handler的概念),这样日志会被存储在制定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为'a'还可以指定为'w'
format:指定handler使用的日志显示格式
datafmt:指定日期时间格式
lever:设置rootlogger的级别日志
stream:用指定的stream创建StreamHandler。可以制定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
%(name)s:Logger的名字,并非用户名,详细查看 %(levelno)s:数字形式的日志级别 %(levelname)s:文本形式的日志级别 %(pathname)s:调用日志输出函数的模块的完整路径名,可能没有 %(filename)s:调用日志输出函数的模块的文件名 %(module)s:调用日志输出函数的模块名 %(funcName)s:调用日志输出函数的函数名 %(lineno)d:调用日志输出函数的语句所在的代码行 %(created)f:当前时间,用UNIX标准的表示时间的浮 点数表示 %(relativeCreated)d:输出日志信息时的,自Logger创建以 来的毫秒数 %(asctime)s:字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒 %(thread)d:线程ID。可能没有 %(threadName)s:线程名。可能没有 %(process)d:进程ID。可能没有 %(message)s:用户输出的消息
如何修改默认的行为 logging.basicConfig(filename="mylog.txt", # 指定的日志文件名 filemode="a", #指定的是文件打开的模式 通常为a level=logging.DEBUG, # 指定级别 format="%(filename)s %(levelname)s %(asctime)s %(message)s",# 指定显示格式 ) logging.info("info") logging.debug("debug") logging.warning("warning") logging.error("error") logging.critical("critical")
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s' logfile_path = "dictconfig.log" LOGGING_DIC = { 'version': 1, 'disable_existing_loggers': False, # 四个key不能随便写 是固定 'formatters': { # standard 表示格式化处理器的名字 相当于变量名称 可以随便写 'standard': { # format是固定的不能随便写 'format': standard_format }, 'simple': { 'format': simple_format }, }, 'filters': {}, 'handlers': { #打印到终端的日志 #console是处理器的名称 可以随便写 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 打印到屏幕 'formatter': 'simple' }, #打印到文件的日志,收集info及以上的日志 'default': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 'formatter': 'standard', 'filename': logfile_path, # 日志文件 'maxBytes': 1024*1024*5, # 日志大小 5M 'backupCount': 5, #日志文件最大个数 'encoding': 'utf-8', # 日志文件的编码 }, }, 'loggers': { #logging.getLogger(__name__)拿到的logger配置 #aa是生成器的名称 可以随便写 'aa': { 'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)传递 日志的继承 }, }, }
二:日志的继承(了解)
# 自己来定义四种核心角色 import logging mylog = logging.getLogger("father") mylog.setLevel(10) handler = logging.FileHandler("father.log") mylog.addHandler(handler) handler.setLevel(10) fmter = logging.Formatter(fmt="%(threadName)s %(funcName)s %(module)s %(filename)s %(levelname)s %(asctime)s %(message)s") handler.setFormatter(fmter) # 在获取一个生成器 同时指定该生成器的父生成器是father这个生成器 sonlog = logging.getLogger("father.son") # 需求:子生成器 的输出位置与父生成器不同 格式相同 sonhandler = logging.FileHandler("son.txt",encoding="utf8") sonlog.addHandler(sonhandler) sonfmt = logging.Formatter(fmt="%(threadName)s %(funcName)s %(module)s %(filename)s %(levelname)s %(asctime)s %(message)s") sonhandler.setFormatter(sonfmt) # 继承后子生成器 可以直接使用父生成器的配置 # mylog.info("这是一条日志信息!") # sonlog.info("这是 son 输出的日志信息!") #子生成器 在生成一个日志时 会自动给父生成器也发一个 # 取消传递效果 sonlog.propagate = False sonlog.info("这是 son 输出的日志信息!")