您当前的位置:首页 > IT编程 > python
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:python 实现多进程日志轮转ConcurrentLogHandler

51自学网 2021-10-30 22:49:18
  python
这篇教程python 实现多进程日志轮转ConcurrentLogHandler写得很实用,希望能帮到您。

记录日志是我们程序中必不可少的一个功能,但是日志文件如果没有合理的管理,时间长了几百兆的日志文件就很难分析了(都不想打开看),但是又不可能经常手动去管理它

日志轮转:根据时间或者文件大小控制日志的文件个数,不用我们手动管理

python中logging模块内置的有几个支持日志轮转的handler

常用的有TimedRotatingFileHandler根据时间轮转 RotatingFileHandler根据文件大小轮转

但是内置的这些handler是多线程安全的,而不支持多进程(可以修改源码加锁保证进程安全)

多进程的时候可以使用ConcurrentLogHandler(需要自行安装)按照文件大小轮转

pip install ConcurrentLogHandler

一、简单的日志轮转功能实现:

#!/usr/bin/env python# -*- coding: utf-8 -*- import osimport loggingfrom cloghandler import ConcurrentRotatingFileHandlerfrom config import LOG_PATH, LOG_FILENAME, LOG_MAX_BYTES  def create_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 # 最多备份几个日志文件):  # 判断存放日志的文件夹是否存在 如果不存在新建  if not os.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对象  return logger # 日志格式formatter_log = logging.Formatter('%(asctime)s - %(filename)s [line: %(lineno)d] 【%(levelname)s】 ----- %(message)s')# 生成一个loggerlogger = create_logger(log_path=LOG_PATH, logger_name="mylogger", formatter=formatter_log)  

这样就可以在其他模块导入logger进行使用了

logger.error("error msg") 

有时候我们会记录一些数据到文件中,如果多个程序同时写入同一文件会把数据写乱 我们也可以使用这个模块来代替f.write()

from config import CHANNEL_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 = DEBUGhandlers = consoleHandler [logger_public]handlers = publicFileHandlerqualname = publicpropagate = 0 [handler_consoleHandler]class = StreamHandlerlevel = DEBUGformatter = my_formatterargs = (sys.stdout,) [handler_publicFileHandler]class = cloghandler.ConcurrentRotatingFileHandlerlevel = INFOformatter = my_formatterkwargs = {"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)sdatefmt = %Y-%m-%d %H:%M:%S 

创建mylogger.py

import loggingimport logging.config logging.config.fileConfig("./xxx.ini") logger = logging.getLogger("public") logger.info("hello world!")

补充:python日志轮转RotatingFileHandler动态加载导致不能记录日志问题

linux下:

Traceback (most recent call last): File “/usr/lib64/python2.7/logging/handlers.py”, line 77, in emit self.doRollover() File “/usr/lib64/python2.7/logging/handlers.py”, line 136, in doRollover os.rename(sfn, dfn) OSError: [Errno 13] Permission denied Logged from file utils.py, line 89

windows下:

Traceback (most recent call last): File “F:/Python27/lib/logging/handlers.py”, line 77, in emit self.doRollover() File “F:/Python27/lib/logging/handlers.py”, line 142, in doRollover os.rename(self.baseFilename, dfn) WindowsError: [Error 32] Logged from file utils.py, line 89

这是由于django开发模式时会同时启动两个进程加载settings.py,导致日志文件占用后无法重命名或者删除

都知道django开发模式下如果有文件变动会自动重新启动,所以同时又两个进程,一个是程序正常运行的进程,另一个是用来监听变更并重启服务的进程,他们都会加载一遍settings.py,可以在settings.py中加print然后启动会看到控制台又两次输出。

解决方式:

python C:/Users/pc/Desktop/yunserver-1.1/manage.py runserver --noreload 0.0.0.0:8000

使用不动态加载方式运行(这样可能会影响开发环境中动态加载)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持51zixue.net。如有错误或未考虑完全的地方,望不吝赐教。


python psutil库的使用示例
使用Python和GDAL给图片加坐标系的实现思路(坐标投影转换)
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。