【踩坑记录】记录一次使用Python logging库多进程打印日志的填坑过程
背景:
- 项目使用Python自带的logging库来打印日志
- 项目部署在一台Centos7的机器上
- 项目采用
gunicorn多进程部署
过程:
1、LOG日志代码封装:
采用logging库,并设置when='MIDNIGHT',以天为单位,进行日志分割,前一天的日志会自动加上前一天的日期,最新日志始终会打印到mock-service.log文件中,以下为log打印的封装
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019/8/8 22:10
# @Author :
# @Site :
# @File : Logger.py
# @Software: PyCharm
"""
日志类。通过读取配置文件,定义日志级别、日志文件名、日志格式等。
一般直接把logger import进去
from utils.log import logger
logger.info('test log')
"""
import os
import platform
import logging
from logging.handlers import TimedRotatingFileHandler
class Logger:
def __init__(self, logger_name='framework'):
self.logger = logging.getLogger(logger_name)
logging.root.setLevel(logging.NOTSET)
if platform.system() == 'Windows':
# win机器路径
self.log_path=os.path.join(os.path.dirname(os.path.dirname(__file__)),'log')
else:
# 服务器路径
self.log_path='/log'
self.log_file_name = 'mock-service.log' # 日志文件
self.backup_count = 30 # 保留的日志数量
# 日志输出级别
self.console_output_level = 'INFO'
self.file_output_level = 'INFO'
# 日志输出格式
pattern = '%(asctime)s - %(filename)s [Line:%(lineno)d] - %(levelname)s - %(message)s'
self.formatter = logging.Formatter(pattern)
def get_logger(self):
"""在logger中添加日志句柄并返回,如果logger已有句柄,则直接返回
我们这里添加两个句柄,一个输出日志到控制台,另一个输出到日志文件。
两个句柄的日志级别不同,在配置文件中可设置。
"""
if not self.logger.handlers: # 避免重复日志
console_handler = logging.StreamHandler()
console_handler.setFormatter(self.formatter)
console_handler.setLevel(self.console_output_level)
self.logger.addHandler(console_handler)
# 每天重新创建一个日志文件,最多保留backup_count份
# 每天生成的日志文件没有后缀,需要修改源码:TimedRotatingFileHandler类下的doRollover方法-->
# dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple)后面拼接后缀名
# dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple) + ".log")
file_handler = TimedRotatingFileHandler(filename=os.path.join(self.log_path, self.log_file_name),
when='MIDNIGHT',
interval=1,
backupCount=self.backup_count,
delay=True,
encoding='utf-8'
)
file_handler.setFormatter(self.formatter)
file_handler.setLevel(self.file_output_level)
self.logger.addHandler(file_handler)
return self.logger
logger = Logger().get_logger()
2、调用LOG封装
实际调用时,采用导包并设置别名的方式进行log打印,以下为实际打印log的demo
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019/12/2 10:32
# @Author :
# @Site :
# @File : 1.py
# @Software: PyCharm
# @Description:
from util.Logger import logger as log
class test1:
def log_test(self):
log.info('log测试')
if __name__ == '__main__':
t = test1()
t.log_test()
3、项目部署环境
该项目目前部署在centos7的一台服务器上面,不过我觉得这个应该和部署在哪里没关系
4、出现的问题(坑,大坑)
项目持续在服务器上面运行着,但有时候会发现,日志根本没有打印到mock-service.log文件中,比如下面这个,12月29的调用日志,打到了27号的log文件中了

解决思路:
1、第一次尝试:
为了找到原因,之前有些调用log打印是写在init方法里面,然后下面的方法用self.log进行调用,后面为了解决这个问题,把所有init里面的初始化都去掉了,现在我觉得问题可能还是出在调用上,日志封装应该没有问题。现在这个项目有些是类方法在打印日志,有些是封装的函数在打印日志。整个项目是用flask框架写的,然后启动run.py文件,我觉得可能是出现在了某一个地方的调用一直占用了日志打印的进程,导致后面再调用日志打印的时候打印到了之前的文件中,只是一个猜测,也不知道怎么去验证这个问题
2、第二次尝试
经过再一次的百度、谷歌查找,发现Python的这个自带的logging库是不支持多进程的,后面查到可通过如下方式进行解决这个问题
关于logging库
不支持多进程的文章:
https://juejin.im/post/5bc2bd3a5188255c94465d31
https://zhuanlan.zhihu.com/p/29557920
- 自行对logging库重写,以解决该问题
- 通过别人已封装好的第三方库
我选择第二种方式,不重复造轮子,经过一番对比,最终选择了这个第三方库concurrent_log,详细的可去github仓库查看,并且作者对重写后的代码进行了测试,证明已解决多线程、多进程的问题
安装方式:
pip3 install concurrent_log
github地址:
https://github.com/huanghyw/concurrent_log
关于自己对logging库重写也是可以的,下面介绍几篇重写的文章
【踩坑记录】记录一次使用Python logging库多进程打印日志的填坑过程的更多相关文章
- 解决多个py模块调用同一个python的logging模块,打印日志冲突问题
前期对python中的logging模块进行了封装,这样自动化测试框架中的多个测试脚本(py)就可以使用同一个封装后的日志系统,这样各脚本中只需要引用一下即可,方面快捷.那么当我使用unittest框 ...
- F2eTest和uirecorder自动化测试环境部署填坑记录
坑1:尝试部署的时候只在opennode.bat里面填写了两个浏览器,测试通过后再增加其他浏览器,页面上一直不显示. 填坑:需要清空数据库里的`wd_browsers`和`wd_nodes`表,然后重 ...
- python web开发-flask中日志的使用
Flask使用日志记录的方式: 初始化flask应用实例 在flask中使用logger,需要初始化一个flask的应用 app = Flask(__name__) 2. 调用logger 直接调用l ...
- 13 python logging模块
原文:http://www.cnblogs.com/dahu-daqing/p/7040764.html 1 logging模块简介 logging模块是Python内置的标准模块,主要用于输出运行日 ...
- Python日志库logging总结-可能是目前为止将logging库总结的最好的一篇文章
在部署项目时,不可能直接将所有的信息都输出到控制台中,我们可以将这些信息记录到日志文件中,这样不仅方便我们查看程序运行时的情况,也可以在项目出现故障时根据运行时产生的日志快速定位问题出现的位置. 1. ...
- [Python3 填坑] 009 深拷贝与浅拷贝
目录 1. print( 坑的信息 ) 2. 开始填坑 2.1 Python3.7 官方文档 2.2 赋值.切片与 copy() 分析 分析 分析 分析 2.3 copy 模块 分析 分析 2.4 小 ...
- Excel填坑[0]
Excel填坑[0] 本着一天水一贴的原则(放p),我又来填坑了.今天做一个很简单的排队图,虽然不难,但因为手机显示问题折腾了半天.感觉做图做表格不仅仅是靠技术,更重要的是思维. 就是这张图,看起来平 ...
- HDP 3.1.0 集成 Sqoop2 踩坑问题记录
HDP 3.1.0 集成 Sqoop2 踩坑问题记录 本文原始地址:https://sitoi.cn/posts/65261.html 问题一 $ sqoop:000> start job -n ...
- lubuntu踩坑全记录
为了降低系统占用,毕业之后一直用lubuntu不用ubuntu...操作其实差不多,就是lubuntu有一些小坑坑:P 本文是我的踩坑全记录.长期更新. 调分辨率 升级命令lubuntu不出登录页面 ...
随机推荐
- Python的类(class)和实例(Instance)如何操作使用
面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可 ...
- 【快学springboot】3.多种接受参数的方式
前往掘金查看:https://juejin.im/post/5d05e5f9f265da1b6c5f74b4 前言 在开发中,我们常常会碰到多种传参的方式.这里,我们就来总结下,springboot中 ...
- linux上实现jmeter分布式压力测试(转)
摘要:最近根据公司工作的需求,学习了一些压力测试的知识,目前,公司使用的是jmeter进行压力测试.下面就记录下近期的学习.我想将这次的博文分成三个部分:1.开始测试前的准备(测试环境的搭建)2.在一 ...
- 如何让浏览器的左上角显示自己的logo的小诀窍
很简单,只需要在head头部加上以下代码 <link rel="icon" href="图片路径" type="image/x-icon&quo ...
- CH11 关联容器
关联容器与顺序容器有着根本的不同:关联容器中的元素是按关键字来保存和访问的,而顺序容器是按它们在容器中的位置来顺序保存和访问的.两个主要的关联容器:map和set map 中的元素的是一个key-va ...
- 时间转换(scanf的指定格式读入)
给定一个12小时制的时间,请将其转换成24小时制的时间.说明:12小时制的午夜12:00:00AM,对应的24小时制时间为00:00:00.12小时制的中午12:00:00PM,对应的24小时制时间为 ...
- 068、Java面向对象之声明两个对象
01.代码如下: package TIANPAN; class Book { // 定义一个新的类 String title; // 书的名字 double price; // 书的价格 public ...
- 机器学习、深度学习中的信息熵、相对熵(KL散度)、交叉熵、条件熵
信息熵 信息量和信息熵的概念最早是出现在通信理论中的,其概念最早是由信息论鼻祖香农在其经典著作<A Mathematical Theory of Communication>中提出的.如今 ...
- Lesson 47 The great escape
What is one of the features of modern camping where nationality is concerned? Economy is one powerfu ...
- 白手起家Django项目发布上篇_linux centos 环境部署
在项目发布之前,首先准备好我们编写好的Django项目,这个我们在之后博客有写,大家可以去看, 首先,先开始安装linux服务器,作为Django项目的发布服务器.以Vmware虚拟机为例子,大家也可 ...