python 实现多进程日志轮转ConcurrentLogHandler

 更新时间:2021年03月15日 10:27:53   作者:qq_41864652  
这篇文章主要介绍了python 实现多进程日志轮转ConcurrentLogHandler,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

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

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

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

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

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

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

pip install ConcurrentLogHandler

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

#!/usr/bin/env python
# -*- coding: utf-8 -*- 
import os
import logging
from cloghandler import ConcurrentRotatingFileHandler
from 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')
# 生成一个logger
logger = 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 = 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

import logging
import 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

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

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

相关文章

  • Django后端接收嵌套Json数据及解析详解

    Django后端接收嵌套Json数据及解析详解

    这篇文章主要介绍了Django后端接收嵌套Json数据及解析详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Python+Opencv实现计算闭合区域面积

    Python+Opencv实现计算闭合区域面积

    这篇文章主要介绍了利用Python Opencv计算闭合区域的面积的原理以及实现代码,文中的讲解详细易懂,感兴趣的小伙伴快跟随小编一起学习一下吧
    2022-03-03
  • Django视图函数的具体使用

    Django视图函数的具体使用

    这篇文章主要介绍了Django视图函数的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Python文件操作与数据处理实战指南

    Python文件操作与数据处理实战指南

    文件操作与数据处理是Python编程中最基础也是最重要的技能之一,无论是数据分析、Web开发还是自动化脚本编写,都离不开对文件的读写和各种数据处理操作,本文将全面介绍Python中的文件操作方法和常用数据处理技巧,需要的朋友可以参考下
    2025-04-04
  • 磁盘垃圾文件清理器python代码实现

    磁盘垃圾文件清理器python代码实现

    几行Python代码打造自己的磁盘垃圾文件清理器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • python禁止位置传参函数详解

    python禁止位置传参函数详解

    文章介绍了Python3.x中的关键字参数特性,说明了如何在函数定义中使用*符号来限制参数只能通过关键字传递,而不是位置,这种特性在处理参数较多或顺序可能导致混淆的函数时特别有用,提高了代码的可读性和健壮性
    2024-11-11
  • Python的信号库Blinker用法详解

    Python的信号库Blinker用法详解

    在本篇文章里小编给大家整理了一篇关于Python的信号库Blinker用法详解内容,有兴趣的朋友们可以学习下。
    2020-12-12
  • Flask自定义序列化超详细讲解

    Flask自定义序列化超详细讲解

    序列化其实就是将数据转化成一种可逆的数据结构,自然,逆向的过程就叫做反序列化。php将数据序列化和反序列化会用到两个函数:serialize 将对象格式化成有序的字符串、unserialize 将字符串还原成原来的对象
    2022-11-11
  • Linux下python与C++使用dlib实现人脸检测

    Linux下python与C++使用dlib实现人脸检测

    这篇文章主要为大家详细介绍了Linux下python与C++使用dlib实现人脸检测,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • Django环境下使用Ajax的操作代码

    Django环境下使用Ajax的操作代码

    AJAX 的主要目标是在不刷新整个页面的情况下,通过后台与服务器进行数据交换和更新页面内容,通过 AJAX,您可以向服务器发送请求并接收响应,然后使用 JavaScript 动态地更新页面的部分内容,这篇文章主要介绍了Django环境下使用Ajax,需要的朋友可以参考下
    2024-03-03

最新评论