版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/y1574406771/article/details/82178891
logging python 中的日志模块
最近尝试使用了python中的日志库 logging, 作简单使用总结
有什么问题或建议请留言告知 , 感谢阅读
简单理解就是 logger 相当于申明了一个外壳
Handler 类似于 logger 的一套规则,来填充 logger ,并告诉 logger 怎么以哪种方式输出日志
自己常用的 handler : StreamHandler, fileHandler
Python 提供了其它的 handler,参考 logging.handlers
Formatter 则表示日志输出格式及内容,以下列一些常用的:
%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息
尝试了log的三种配置方式:
1. basicConfig 配置方式
conf_format = ' [ %(asctime)-15s ] - %(name)s - %(levelname)s - %(pathname)s[line : %(lineno)d] - FUNNAME : [%(funcName)s] - MESSAGE : %(message)s '
def log_test_first():
'''
first method 单个日志文件,同时打印控制台
'''
try:
print(sys.stdout.__dict__)
console = logging.StreamHandler(sys.stdout) ##StreamHandler 能够将日志信息输出到sys.stdout, sys.stderr 或者类文件对象
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
##
## basicConfig方法 传入filename会自动构造一个filehandler 传入stream则会自动构造一个StreamHandler
## 但二者不可同时传入 同时传入默认使用filename参数 stream会被忽略
logging.basicConfig(
level=logging.INFO,
format=conf_format,
datefmt='%Y/%m/%d %H:%M:%S',
filename=f"./{os.path.split(__file__)[-1].split('.')[0]}.log",
filemode='w' )
logging.getLogger('').addHandler(console)
logger = logging.getLogger('First method')
logger.info('Log_test_first_test-AAAAAAAAAAAAAAAA')
except Exception :
traceback.print_exc()
def log_test_second():
'''
second method 多个日志文件,同时打印控制台, 同一个formatter 并且udp推日志到 syslog 服务处理
SysLogHandler
'''
try:
syslog = logging.handlers.SysLogHandler(address=("0.0.0.0", 514), socktype=socket.SOCK_DGRAM)
syslog.setFormatter(
logging.Formatter('%(asctime)s,%(msecs)03d [%(levelname)s] [%(name)s] %(funcName)s %(lineno)d: %(message)s')
)
logging.basicConfig(level=logging.DEBUG,
format=conf_format,
handlers=[logging.FileHandler("example1.log"),
syslog,
logging.FileHandler("example2.log"),
logging.StreamHandler()])
logging.getLogger(__name__)
logging.info('xxx')
except Exception as e:
traceback.print_exc()
2. logging.config.dictConfig 构造 json 配置方式 多个format 多个handler
def log_test_third():
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
## 声明2个format
'formatters': {
'simple': {'format': '%(levelname)s %(message)s'},
'default': { 'format' : '%(asctime)s %(message)s', 'datefmt' : '%Y-%m-%d %H:%M:%S'
}
},
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
'formatter': 'simple',
"stream": sys.stderr
},
'file': {
'level': 'INFO',
'class': 'logging.FileHandler',
'formatter': 'default',
'filename' : 'example3.log',
}
},
'loggers' : {
# 定义了一个logger
'mylogger' : {
'level' : 'DEBUG',
'handlers' : [ 'file'],
'propagate' : True
},
'mylogger_console' : {
'level' : 'DEBUG',
'handlers' : ['console'],
'propagate' : True
}
}
}
logging.config.dictConfig(LOGGING)
logger = logging.getLogger('mylogger_console')
logger.info('test')
3. logging.config.fileConfig() 配置文件方式
## 配置文件 log.conf :
[loggers] # logger 名称
keys=root,mylogger
[handlers] # handlers 名称
keys=console,file
[formatters]
keys=verbose,simple,default
[formatter_verbose]
format=%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s
datefmt=
class=logging.Formatter
[formatter_simple]
format=%(levelname)s %(message)s
datefmt=
class=logging.Formatter
[formatter_default]
format=%(asctime)s %(message)s
datefmt=%Y-%m-%d %H:%M:%S
class=logging.Formatter
[logger_mylogger]
level=DEBUG
handlers=console,file
propagate=1
qualname=lyj
[logger_root]
level=NOTSET
handlers=
[handler_console]
class=StreamHandler
level=DEBUG
args=()
[handler_file]
class=FileHandler
level=INFO
formatter=default
args=('file_version.log','a')
; [handler_file]
; class=handlers.TimedRotatingFileHandler
; level=INFO
; formatter=default
; args=('log','M',1,0,'utf8')
python代码:
def log_test_fourth():
logging.config.fileConfig('log.conf')
logger = logging.getLogger('lyj.root')
logger.info('xxxx')
个人觉得json配置方式最为可读 。