python标准库中的logging模块在记录日志时经常会用到,但在实际使用发现它自带的用于本地日志回滚的类

logging.handlers.RotatingFileHandler 在多进程环境下会出现不同进程向不同文件写的问题,原因就是在当前

日志文件写满后回滚的时候没有处理好并发问题(或者可以说基本没处理),因此自己实现了一个相似功能的类,

本来是打算使用多进程锁,写完后发现没啥用。。。,于是就新建了一个.lock文件作为锁来处理多进程。用文件的

修改时间来控制只能有一个进程访问。

  代码如下:

#coding=utf-8
import os
import sys
import json
import time
import logging
import traceback
import logging.handlers
from multiprocessing import Lock class SpiderRotatingFileHandler(logging.handlers.RotatingFileHandler):
u'''
文件回滚日志处理器
特点:
1. 利用备份文件修改时间做判断 修复了多进程下同时多个日志文件被写入的bug
2. 可选项 使用json格式记录日志文件 '''
def __init__(self, filename, mode='a', maxBytes=0,
backupCount=0, encoding=None, delay=0, is_json=False):
logging.handlers.RotatingFileHandler.__init__(self,
filename, mode, maxBytes, backupCount, encoding, delay)
# 格式处理器
self.Formatter = logging.Formatter()
# 进程锁
self.my_lock = Lock() self.is_json = is_json
if self.is_json:
self.format = self.json_format def json_format(self, record):
u'''
json 格式化日志
@record: 日志记录对象
type: logging.LogRecord
'''
# 增加 asctime 属性
record.asctime = self.Formatter.formatTime(record)
#
message = record.getMessage()
log_data = {}
# 检查是否为json格式 并且是字典形式
try:
log_data = json.loads(message)
if not isinstance(log_data, dict):
log_data = {}
except Exception as e:
exc_info = traceback.format_exc()
#sys.stderr.write(exc_info) # 获取日志基本信息
log_record_basic_fields = [
"levelname", "filename", "lineno",
"name", "created", "asctime",
] if not log_data:
log_data.update({
"_message": message,
}) for attr in log_record_basic_fields:
value = getattr(record, attr, "")
log_data.update({
"_{}".format(attr): value,
})
try:
result = json.dumps(log_data, ensure_ascii=False)
except:
result = json.dumps(log_data)
return result def doRollover(self):
"""
Do a rollover, as described in __init__().
"""
with self.my_lock:
if self.stream:
self.stream.close()
self.stream = None
lock_file = "%s.lock"%self.baseFilename
max_modify_interval = 3 # seconds
do_flag = 0 # 利用 Lock 文件被修改时间保证不会出现同时多个文件被写入
if not os.path.exists(lock_file):
with open(lock_file, "w"):
pass
do_flag = 1
elif time.time() - os.stat(lock_file).st_mtime > max_modify_interval:
do_flag = 1
else:
pass
if do_flag:
for i in range(self.backupCount - 1, 0, -1):
sfn = "%s.%d" % (self.baseFilename, i)
dfn = "%s.%d" % (self.baseFilename, i + 1)
if os.path.exists(sfn):
# 删除最大备份文件
if os.path.exists(dfn):
os.remove(dfn)
os.rename(sfn, dfn) dfn = self.baseFilename + ".1"
if os.path.exists(dfn):
os.remove(dfn) if os.path.exists(self.baseFilename):
os.rename(self.baseFilename, dfn)
# 刷新 Lock 文件修改时间
with open(lock_file, "w"):
pass if not self.delay:
self.stream = self._open()
return

  经过测试后发现,日志文件不再出现混乱写入(不过总感觉 3 秒好像还会出现点问题,万一在3秒内写满了日

志文件可能会造成日志文件大小超过限制。)

  json格式的日志输出算是附加的功能吧

  ok,欢迎找茬

python logging 实现的进程安全的文件回滚日志类的更多相关文章

  1. Log4net入门(回滚日志文件篇)

    在上一篇Log4net(日志文件篇)中,我们使用"log4net.Appender.FileAppender"将日志信息输出到一个单一的文件中,随着应用程序的持续使用,该日志文件会 ...

  2. git本地文件回滚操作

    今天有几个文件改在了其他分支上.需要回滚. 参考了下面两篇文章: Link    Link 简单讲,分多个不同的阶段: 1. 用git status命令看,发现是unstaged,那么就是只在work ...

  3. git 文件回滚

    场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file.场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第 ...

  4. python logging日志模块

    一.logging模块的简介 logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级.日志保存路径.日志文件回滚等:相比print,具备如下优点: 可以通过设置不 ...

  5. (转)python logging模块

    python logging模块 原文:http://www.cnblogs.com/dahu-daqing/p/7040764.html 1 logging模块简介 logging模块是Python ...

  6. 13 python logging模块

    原文:http://www.cnblogs.com/dahu-daqing/p/7040764.html 1 logging模块简介 logging模块是Python内置的标准模块,主要用于输出运行日 ...

  7. python logging模块【转载】

    转自:https://www.cnblogs.com/dahu-daqing/p/7040764.html 参考:老顽童log模块,讲的很细致,基本上拿到手就可以直接用了,很赞 1 logging模块 ...

  8. python logging模块

    1.logging模块提供了四个组件logger:日志类,有两个功能1)配置日志的等级,处理器handler,过滤器filterlogger.setLevel(logging.INFO)logger. ...

  9. 利用lsof恢复进程占用的文件

    说明:经常会遇到这种情况,没有使用正确的方式清理进程占用的文件,比如日志.导致空间并没有释放.也有的时候需要恢复进程占用的文件. 解决方式 lsof |grep del # 找出自己要恢复的文件名称. ...

随机推荐

  1. flask_sqlalchemy

    简介: flask_sqlalchemy 是 Flask Web 框架的一个扩展. 使 Web 服务器以 (ORM: Object Relational Mapping) 对象关系映射的方式与数据库交 ...

  2. Eclipse json文件报错

    只要找一个json在线解析,验证你的json文件格式的正确性,错误可以忽略. 如要消除红叉,关闭Json Validation即可,如下操作: Window > Preferences > ...

  3. JSP通过表格显示数据库的信息

    [step one] 1-1 建立数据库 在jsp中,我们使用的是mysql数据库,对于此数据的优缺点本篇不予以讲述,首先建立news数据库,其数据库中表的信息为: eg:< id :1 ; n ...

  4. C# 窗口页面卡的处理方案-异步编程委托

    今天用winform做了一个小程序,主要是用于远程数据的登录采集,因为数据量非常大,到时每次点击按钮执行程序的时候界面都会出现假死状态,具体表现是无法拖动窗口,无法最小化或关闭等,只能任务管理进程结束 ...

  5. 关于EL表达式取值的问题

    EL表达式取值时,如果没有指定作用域,EL表达式会自动按照作用域的大小,从小到大依次去找;比如${s},会自动按照"pageContext,request,session,applicati ...

  6. Interrupt handler

    1.处理器上的中断硬件关系图 2. 中断处理例程 3. 顶半部与底半部

  7. R包和python对应的库

    数据库 类别 Python R MySQL mysql-connector-python(官方) RMySQL Oracle cx_Oracle ROracle Redis redis rredis ...

  8. Java8 Map的遍历方式

    在这篇文章中,我将对Map的遍历方式做一个对比和总结,将分别从JAVA8之前和JAVA8做一个遍历方式的对比,亲测可行. public class LambdaMap { private Map< ...

  9. java基础六 [异常处理](阅读Head First Java记录)

    在程序运行时,我们不能保证所有服务和方法都是正确的,如果发生问题报错会导致程序崩溃,所以需要对一些可以预见的错误进行异常处理,通过throw去抛出一个异常,然后用try..catch..将要执行的该方 ...

  10. poj2456(二分+贪心)

    题目链接:http://poj.org/problem?id=2456 题意: 有n个呈线性排列的牲畜堋,给出其坐标,有c头牛,求把两头牛的最短距离的最大值. 思路: 先将坐标排个序.两头牛的最短距离 ...