python 实现多进程日志轮转ConcurrentLogHandler
记录日志是我们程序中必不可少的一个功能,但是日志文件如果没有合理的管理,时间长了几百兆的日志文件就很难分析了(都不想打开看),但是又不可能经常手动去管理它
日志轮转:根据时间或者文件大小控制日志的文件个数,不用我们手动管理
python中logging模块内置的有几个支持日志轮转的handler
常用的有TimedRotatingFileHandler根据时间轮转RotatingFileHandler根据文件大小轮转
但是内置的这些handler是多线程安全的,而不支持多进程(可以修改源码加锁保证进程安全)
多进程的时候可以使用ConcurrentLogHandler(需要自行安装)按照文件大小轮转
pipinstallConcurrentLogHandler
一、简单的日志轮转功能实现:
#!/usr/bin/envpython
#-*-coding:utf-8-*-
importos
importlogging
fromcloghandlerimportConcurrentRotatingFileHandler
fromconfigimportLOG_PATH,LOG_FILENAME,LOG_MAX_BYTES
defcreate_logger(log_path=os.getcwd(),#存放日志的目录
level=logging.DEBUG,
formatter=logging.BASIC_FORMAT,#日志输出格式
logger_name="",#可以使用logging.getlogger(logger_name)使用此logger
mode='a',
delay=0,
debug=True,
log_filename=LOG_FILENAME,#保存日志的文件名(备份出的文件会以此名+.1、.2命名)
encoding=None,
maxBytes=LOG_MAX_BYTES,#每个日志文件的最大容量
backupCount=3#最多备份几个日志文件):
#判断存放日志的文件夹是否存在如果不存在新建
ifnotos.path.exists(log_path):
os.mkdir(log_path)
#存放log的文件名
log_filename=os.path.join(log_path,log_filename)
#创建一个logger
logger=logging.getLogger(logger_name)
#设置日志等级
logger.setLevel(level)
#创建一个滚动日志处理器
crfh=ConcurrentRotatingFileHandler(log_filename,mode=mode,maxBytes=maxBytes,backupCount=backupCount,delay=delay,debug=debug,encoding=encoding)
#定义handler的输出格式
#设定日志输出格式
crfh.setFormatter(formatter)
#添加日志处理器
logger.addHandler(crfh)
#返回logger对象
returnlogger
#日志格式
formatter_log=logging.Formatter('%(asctime)s-%(filename)s[line:%(lineno)d]【%(levelname)s】-----%(message)s')
#生成一个logger
logger=create_logger(log_path=LOG_PATH,logger_name="mylogger",formatter=formatter_log)
这样就可以在其他模块导入logger进行使用了
logger.error("errormsg")
有时候我们会记录一些数据到文件中,如果多个程序同时写入同一文件会把数据写乱我们也可以使用这个模块来代替f.write()
fromconfigimportCHANNEL_PATH,CHANNEL_FILENAME,LOG_MAX_BYTES
#只需要把日志的格式改为只存入信息就可以了
formatter_writer=logging.Formatter('%(message)s')
#创建一个写入器(logger)
writer=create_logger(logger_name="writer",log_path=CHANNEL_PATH,log_filename=CHANNEL_FILENAME,formatter=formatter_writer,level=logging.INFO)
这样就可以使用writer.info("msg")记录数据了
二、使用ini配置文件
创建文件xxx.ini
[loggers]
keys=root,public
[handlers]
keys=consoleHandler,publicFileHandler
[formatters]
keys=my_formatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_public]
handlers=publicFileHandler
qualname=public
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=my_formatter
args=(sys.stdout,)
[handler_publicFileHandler]
class=cloghandler.ConcurrentRotatingFileHandler
level=INFO
formatter=my_formatter
kwargs={"filename":"./logs/public.log","maxBytes":1024*1024*10,"backupCount":10,"delay":True,"debug":True}
[formatter_my_formatter]
format=%(asctime)s-%(filename)s[line:%(lineno)d][%(levelname)s]-----%(message)s
datefmt=%Y-%m-%d%H:%M:%S
创建mylogger.py
importlogging
importlogging.config
logging.config.fileConfig("./xxx.ini")
logger=logging.getLogger("public")
logger.info("helloworld!")
补充:python日志轮转RotatingFileHandler动态加载导致不能记录日志问题
linux下:
Traceback(mostrecentcalllast):File“/usr/lib64/python2.7/logging/handlers.py”,line77,inemitself.doRollover()File“/usr/lib64/python2.7/logging/handlers.py”,line136,indoRolloveros.rename(sfn,dfn)OSError:[Errno13]PermissiondeniedLoggedfromfileutils.py,line89
windows下:
Traceback(mostrecentcalllast):File“F:\Python27\lib\logging\handlers.py”,line77,inemitself.doRollover()File“F:\Python27\lib\logging\handlers.py”,line142,indoRolloveros.rename(self.baseFilename,dfn)WindowsError:[Error32]Loggedfromfileutils.py,line89
这是由于django开发模式时会同时启动两个进程加载settings.py,导致日志文件占用后无法重命名或者删除
都知道django开发模式下如果有文件变动会自动重新启动,所以同时又两个进程,一个是程序正常运行的进程,另一个是用来监听变更并重启服务的进程,他们都会加载一遍settings.py,可以在settings.py中加print然后启动会看到控制台又两次输出。
解决方式:
pythonC:\Users\pc\Desktop\yunserver-1.1\manage.pyrunserver--noreload0.0.0.0:8000
使用不动态加载方式运行(这样可能会影响开发环境中动态加载)
以上为个人经验,希望能给大家一个参考,也希望大家多多支持毛票票。如有错误或未考虑完全的地方,望不吝赐教。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。