目录:
1.1.logging日志用途(tcy)https://mp.csdn.net/postedit/95102043
1.2.logging日志流处理流程 https://blog.csdn.net/tcy23456/article/details/95102217
2.1.logging模块级函数 https: //mp.csdn.net/postedit/95102425
2.2.Logger类 https://mp.csdn.net/postedit/95102590
2.3.Handler类 https://mp.csdn.net/postedit/95102690
2.4.Formater类 https://mp.csdn.net/postedit/95102834
2.5.Filter类 https://mp.csdn.net/postedit/95103238
3.1.logging.basicConfig https://mp.csdn.net/postedit/95103385
3.2.配置logging的几种方式 https://mp.csdn.net/postedit/95103602
4.1.日志切割 https://mp.csdn.net/postedit/95103779
4.2.日志滚动和过期删除 https://mp.csdn.net/postedit/95103902
4.3.多模块调用logging https://mp.csdn.net/postedit/95104089
4.4.日志类封装 https://mp.csdn.net/postedit/95104392
4.5.用logging模块记录异常 https://mp.csdn.net/postedit/95104529
作为开发者,我们可以通过以下3中方式来配置logging:
fileConfig()
函数来读取该文件的内容;dictConfig()
函数;logging.basicConfig()也属于第一种方式,只是对loggers, handlers和formatters函数进行封装。
配置二将配置信息和代码分离,降低日志维护成本,使得非开发人员也能够修改日志配置。
# 创建一个日志器logger并设置其日志级别为DEBUG
logger = logging.getLogger('simple_logger')
logger.setLevel(logging.DEBUG)
# 创建一个流处理器handler并设置其日志级别为DEBUG
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
# 创建一个格式器formatter并将其添加到处理器handler
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
# 为日志器logger添加上面创建的处理器handler
logger.addHandler(handler)
# 日志输出
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
"""
2019-07-03 19:12:15,542 - simple_logger - DEBUG - debug message
2019-07-03 19:12:15,542 - simple_logger - INFO - info message
2019-07-03 19:12:15,542 - simple_logger - WARNING - warn message
2019-07-03 19:12:15,542 - simple_logger - ERROR - error message
2019-07-03 19:12:15,542 - simple_logger - CRITICAL - critical message
"""
import logging.config
# 读取日志配置文件内容
logging.config.fileConfig('logging.conf')
# 创建一个日志器logger
logger = logging.getLogger('simpleExample')
# 日志输出
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
配置文件logging.conf内容:(不能包含中文注释,可含英文注释)
[loggers] #必须包含
keys=root,simpleExample #一定要包含root这个值
[handlers] #必须包含
keys=fileHandler,consoleHandler#handler名字列表,必须在配置文件中有对应的section定义
[formatters] #必须包含
keys=simpleFormatter
[logger_root] #指定日志器;必须指定level和handlers这两个option
level=DEBUG
handlers=fileHandler
[logger_simpleExample]#指定日志器
level=DEBUG #DEBUG、INFO、WARNING、ERROR、CRITICAL、NOTSET
(所有级别包括用户定义级别;系统会查找高层次logger来决定logger的有效level)
handlers=consoleHandler
qualname=simpleExample#非root logger来说qualname是必须;表示在logger层级中名字,在应用代码中通过这个名字得到logger
propagate=0 #可选项,其默认是为1,表示消息将会传递给高层次logger的handler
[handler_consoleHandler] #指定处理器
class=StreamHandler #必须指定;表示用于创建handler的类名
args=(sys.stdout,) #必须;表示传递给class所指定handler类初始化方法参数;必是元组
level=DEBUG #可选
formatter=simpleFormatter#可选;指定格式器名称必须出现在formatters这个section中,
配置文件必有这个formatter的section定义;如不指定formatter则该handler会以消息本身作为日志消息进行记录,
而不添加额外的时间、日志器名称等信息;
[handler_fileHandler] #指定处理器
class=FileHandler
args=('logging.log', 'a')
level=ERROR
formatter=simpleFormatter
[formatter_simpleFormatter] #指定格式器;都是可选
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s#指定格式字符串,默认为消息字符串本身
datefmt=#用于指定asctime的时间格式,默认为'%Y-%m-%d %H:%M:%S'
说明:
class指定类名默认为logging.Formatter,该类名可以是相对于logging模块的相对值,如:FileHandler、
handlers.TimeRotatingFileHandler;也可以是一个绝对路径值,
通过普通的import机制来解析,如自定义的handler类mypackage.mymodule.MyHandler
但是mypackage需要在Python可用的导入路径中--sys.path。
输出:propagate=1除了在控制台有输出信息时候,在logging.log文件中也有内容输出
2019-07-03 19:31:51,634 - simpleExample - DEBUG - debug message
2019-07-03 19:31:51,635 - simpleExample - INFO - info message
2019-07-03 19:31:51,635 - simpleExample - WARNING - warn message
2019-07-03 19:31:51,635 - simpleExample - ERROR - error message
2019-07-03 19:31:51,635 - simpleExample - CRITICAL - critical message
pip install PyYAML
Python代码:
import logging
import logging.config
import yaml
with open('logging.yml', 'r') as f_conf:
dict_conf = yaml.load(f_conf)
logging.config.dictConfig(dict_conf)
logger = logging.getLogger('simpleExample')
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
logging.yml配置文件的内容:
version: 1
formatters:
simple:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
console_err:
class: logging.StreamHandler
level: ERROR
formatter: simple
stream: ext://sys.stderr
loggers:
simpleExample:
level: DEBUG
handlers: [console]
propagate: yes
root:
level: DEBUG
handlers: [console_err]
输出结果:
"""
2019-07-04 21:03:31,879 - simpleExample - CRITICAL - critical message
2019-07-04 21:03:31,878 - simpleExample - DEBUG - debug message
2019-07-04 21:03:31,879 - simpleExample - INFO - info message
2019-07-04 21:03:31,879 - simpleExample - WARNING - warn message
2019-07-04 21:03:31,879 - simpleExample - ERROR - error message
2019-07-04 21:03:31,879 - simpleExample - CRITICAL - critical message
"""
logging.config.dictConfig(config)
该函数可以从一个字典对象中获取日志配置信息,config参数就是这个字典对象
key名称 | 描述 |
version | 必选,整数,表示配置格式版本,当前唯一可用的值就是1 |
formatters | 可选,字典,key为格式器名称,value为格式器的配置信息,如format和datefmt |
filters | 可选,字典,key为过滤器名称,value为过滤器的配置信息,如name |
handlers | 可选,字典,key为处理器名称,value为处理器的配置信息,如class、level、formatter和filters,其中class必选项,其它可选;其他配置信息将会传递给class所指定的处理器类的构造函数,如下面的handlers定义示例中的stream、filename、maxBytes和backupCount等 |
loggers | 可选,字典,key为日志器名称,value为日志器的配置信息,如level、handlers、filters 和 propagate(yes |
root | 可选,这是root logger的配置信息,其值也是一个字典对象。除非在定义其它logger时明确指定propagate值为no,否则root logger定义的handlers都会被作用到其它logger上 |
incremental | 可选,默认False。如定义对象已存在,对这些对象定义是否应用到已存在对象上。False表示已存在的对象将会被重新定义。 |
disable_existing_loggers | 可选,默认True。指定是否禁用已存在的日志器loggers,如incremental值为True则该选项将会被忽略 |
#!/usr/bin/env python
# coding:UTF-8
"""
@version: python3.x
@author:dtcy
@contact: [email protected]
@software: PyCharm
@file: 使用配置文件设置logger的配置(logging.config).py
@time: 2018/11/16 13:26
"""
import os,logging,sys,time,json
import logging.config
def singleton(cls):
instances = {}
def _singleton(*args,**kwargs):
if cls not in instances:
instances[cls] = cls(*args,**kwargs)
return instances[cls]
return _singleton
@singleton
class Logger():
def __init__(self,logfile=None):
self.logger = logging.getLogger("simple_example")
with open("logconf.json","r") as config:
LOGGING_CONFIG = json.load(config)
logging.config.dictConfig(LOGGING_CONFIG)
if __name__ == "__main__":
lg = Logger()
lg.logger.warning("aaa1")
lg.logger.error("bbb2")
lg.logger.debug("ccc3")
logconf.json文件内容:
{
"version":1,
"handlers":{
"console_streamHandler":{
"class":"logging.StreamHandler",
"level":"DEBUG",
"formatter":"myFormatter",
"stream":"ext://sys.stdout"
},
"console1_fileHandler":{
"class":"logging.handlers.RotatingFileHandler",
"level":"DEBUG",
"formatter":"myFormatter",
"filename":"log.log",
"mode": "w+",
"maxBytes": 524288000,
"backupCount": 20,
"encoding":"utf8"
}
},
"formatters":{
"myFormatter":{
"format":"%(asctime)s %(name)s %(levelname)s %(filename)s %(lineno)d %(thread)d %(threadName)s %(process)d %(message)s"
}
},
"loggers":{
"simple_example":{
"level":"DEBUG",
"handlers":["console_streamHandler","console1_fileHandler"]
}
}
}
结果显示:
2019-07-04 21:05:34,858 simple_example WARNING test_pprint.py 47 11144 MainThread 11252 aaa1
2019-07-04 21:05:34,867 simple_example ERROR test_pprint.py 48 11144 MainThread 11252 bbb2
2019-07-04 21:05:34,868 simple_example DEBUG test_pprint.py 49 11144 MainThread 11252 ccc3
通过YAML文件配置
通过YAML文件进行配置,比JSON看起来更加简介明了
version: 1
disable_existing_loggers:False
formatters:
simple:
format:"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
handlers:
console:
class:
logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext: // sys.stdout
info_file_handler:
class:
logging.handlers.RotatingFileHandler
level: INFO
formatter: simple
filename: info.log
maxBytes: 10485760
backupCount: 20
encoding: utf8
error_file_handler:
class:
logging.handlers.RotatingFileHandler
level: ERROR
formatter: simple
filename: errors.log
maxBytes:10485760
backupCount: 20
encoding: utf8
loggers:
my_module:
level: ERROR
handlers: [info_file_handler]
propagate: no
root:
level: INFO
handlers: [console, info_file_handler, error_file_handler]
通过YAML加载配置文件,然后通过logging.dictConfig配置logging,
importyaml
importlogging.config
importos
defsetup_logging(default_path="logging.yaml", default_level=logging.INFO, env_key="LOG_CFG"):
path = default_path
value = os.getenv(env_key,None)
ifvalue:
path = value
ifos.path.exists(path):
withopen(path,"r")asf:
config = yaml.load(f)
logging.config.dictConfig(config)
else:
logging.basicConfig(level=default_level)
deffunc():
logging.info("startfunc" )
logging.info("exec func")
logging.info("end func")
if__name__ =="__main__":
setup_logging( default_path="logging.yaml" )
func()
3.通过JSON或者YAML文件配置logging模块
尽管可以在Python代码中配置logging,但是这样并不够灵活,最好的方法是使用一个配置文件来配置。
可以从字典中加载logging配置,也就意味着可以通过JSON或者YAML文件加载日志的配置。
3.1.通过JSON文件配置
JSON配置文件,
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"simple": {
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "simple",
"stream": "ext://sys.stdout"
},
"info_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"level": "INFO",
"formatter": "simple",
"filename": "info.log",
"maxBytes": "10485760",
"backupCount": 20,
"encoding": "utf8"
},
"error_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"level": "ERROR",
"formatter": "simple",
"filename": "errors.log",
"maxBytes": 10485760,
"backupCount": 20,
"encoding": "utf8"
}
},
"loggers": {
"my_module": {
"level": "ERROR",
"handlers": ["info_file_handler"],
"propagate": "no"
}
},
"root": {
"level": "INFO",
"handlers": ["console", "info_file_handler", "error_file_handler"]
}
}
通过JSON加载配置文件,然后通过logging.dictConfig配置logging,
import json
import logging.config
import os
def setup_logging(default_path="logging.json", default_level=logging.INFO, env_key="LOG_CFG"):
path = default_path
value = os.getenv(env_key, None)
if value:
path = value
if os.path.exists(path):
with open(path, "r") as f:
config = json.load(f)
logging.config.dictConfig(config)
else:
logging.basicConfig(level=default_level)
def func():
logging.info("start func")
logging.info("exec func")
logging.info("end func")
if __name__ == "__main__":
setup_logging(default_path="logging.json")
func()