Python多进程记录日志
2015-10-28 18:23
591 查看
用gevent(或封装了gevent的gunicore)启动python进程,会出现多个独立进程同时写一个日志文件,
可以观察到有日志部分丢失:一个进程日志没写完,另一个进程把日志覆盖在同一行的后面;有些日志甚至完全丢失。
用mlogging包可以解决多进程写日志的问题,没有发现不完整的日志,是否丢失日志有待进一步检测。
下面是一个在python程序中记录重要信息,以便以后解析统计的函数
Python代码
# -*- coding: utf-8 -*-
import os.path
import logging
from mlogging import FileHandler_MP, TimedRotatingFileHandler_MP
from functools import partial
class LevelFilter(logging.Filter):
def __init__(self, level, *args, **kwargs):
#super(LevelFilter, self).__init__(*args, **kwargs)
self.level = level
def filter(self, record):
return record.levelno == self.level
def init_info_logger(name, logging_dir):
logging_file = os.path.join(logging_dir, name+".log")
handler = TimedRotatingFileHandler_MP(logging_file, "midnight", 1)
handler.setFormatter( logging.Formatter(
"%(asctime)s %(levelname)-8s %(name)-20s %(message)s", #设置日志格式,固定宽度便于解析
datefmt = "%Y-%m-%d %H:%M:%S" #设置asctime时间格式
))
handler.suffix = "%Y%m%d"
#只记录INFO级别信息,抛弃上面的WARNING、ERROR、CRITICAL几个级别
handler.addFilter( LevelFilter(logging.INFO) )
logger = logging.getLogger(name)
logger.setLevel(logging.INFO)
#有些Python版本会报错KeyError,找不到clientip或user,这里用一个短横(-)做默认值
extra={"clientip":"-", "user":"-"}
#exc_info是出错时的Debug详细回溯信息,这里禁止记录,只记录错误信息这一行
setattr(logger, "info", partial(logger.info, exc_info=False, extra=extra))
logger.addHandler( handler )
return logger
def init_error_logger(logging_dir):
logging_file = os.path.join(logging_dir, "errors.log")
handler = FileHandler_MP(logging_file)
handler.setFormatter( logging.Formatter(
"%(asctime)s %(levelname)-8s %(message)s", #设置日志格式,固定宽度便于解析
datefmt = "%Y-%m-%d %H:%M:%S" #设置asctime时间格式
))
logger = logging.getLogger()
logger.setLevel(logging.WARNING)
#有些Python版本会报错KeyError,找不到clientip或user,这里用一个短横(-)做默认值
extra={"clientip":"-", "user":"-"}
#exc_info是出错时的Debug详细回溯信息
setattr(logger, "critical", partial(logger.critical, exc_info=True, extra=extra))
setattr(logger, "error", partial(logger.error, exc_info=True, extra=extra))
setattr(logger, "warning", partial(logger.warning, exc_info=True, extra=extra))
logger.addHandler( handler )
return logger
if __name__ == "__main__":
logger = init_info_logger("test", "./")
logger.debug("低级别的DEBUG,不会记录。")
logger.info("哈哈哈,这才是我想要的信息,请记下来。")
logger.error("高级别的ERROR,也被过滤掉。")
可以观察到有日志部分丢失:一个进程日志没写完,另一个进程把日志覆盖在同一行的后面;有些日志甚至完全丢失。
用mlogging包可以解决多进程写日志的问题,没有发现不完整的日志,是否丢失日志有待进一步检测。
下面是一个在python程序中记录重要信息,以便以后解析统计的函数
Python代码
# -*- coding: utf-8 -*-
import os.path
import logging
from mlogging import FileHandler_MP, TimedRotatingFileHandler_MP
from functools import partial
class LevelFilter(logging.Filter):
def __init__(self, level, *args, **kwargs):
#super(LevelFilter, self).__init__(*args, **kwargs)
self.level = level
def filter(self, record):
return record.levelno == self.level
def init_info_logger(name, logging_dir):
logging_file = os.path.join(logging_dir, name+".log")
handler = TimedRotatingFileHandler_MP(logging_file, "midnight", 1)
handler.setFormatter( logging.Formatter(
"%(asctime)s %(levelname)-8s %(name)-20s %(message)s", #设置日志格式,固定宽度便于解析
datefmt = "%Y-%m-%d %H:%M:%S" #设置asctime时间格式
))
handler.suffix = "%Y%m%d"
#只记录INFO级别信息,抛弃上面的WARNING、ERROR、CRITICAL几个级别
handler.addFilter( LevelFilter(logging.INFO) )
logger = logging.getLogger(name)
logger.setLevel(logging.INFO)
#有些Python版本会报错KeyError,找不到clientip或user,这里用一个短横(-)做默认值
extra={"clientip":"-", "user":"-"}
#exc_info是出错时的Debug详细回溯信息,这里禁止记录,只记录错误信息这一行
setattr(logger, "info", partial(logger.info, exc_info=False, extra=extra))
logger.addHandler( handler )
return logger
def init_error_logger(logging_dir):
logging_file = os.path.join(logging_dir, "errors.log")
handler = FileHandler_MP(logging_file)
handler.setFormatter( logging.Formatter(
"%(asctime)s %(levelname)-8s %(message)s", #设置日志格式,固定宽度便于解析
datefmt = "%Y-%m-%d %H:%M:%S" #设置asctime时间格式
))
logger = logging.getLogger()
logger.setLevel(logging.WARNING)
#有些Python版本会报错KeyError,找不到clientip或user,这里用一个短横(-)做默认值
extra={"clientip":"-", "user":"-"}
#exc_info是出错时的Debug详细回溯信息
setattr(logger, "critical", partial(logger.critical, exc_info=True, extra=extra))
setattr(logger, "error", partial(logger.error, exc_info=True, extra=extra))
setattr(logger, "warning", partial(logger.warning, exc_info=True, extra=extra))
logger.addHandler( handler )
return logger
if __name__ == "__main__":
logger = init_info_logger("test", "./")
logger.debug("低级别的DEBUG,不会记录。")
logger.info("哈哈哈,这才是我想要的信息,请记下来。")
logger.error("高级别的ERROR,也被过滤掉。")
相关文章推荐
- Python *与** 参数问题
- 使用python进行数据转码
- python函数参数带星号*
- (5)python循环语句
- python爬虫学习笔记1——糗百段子爬取
- Python的几种实现
- Python的几种实现
- python多线程机制
- Python操作Excel读写--xlrd、xlwt模块
- Spinbox 实例
- 使用python,批量导入数据到elasticsearch中
- Python-os与shutil对文件和文件夹的操作
- python--随机函数(random,uniform,randint,randrange,shuffle,sample)
- Python语句概述20
- Python多线程
- Python 第一课
- 使用Python开发CouchDB介绍
- Scale 实例
- Python 3 安装 lxml 报错Unable to find vcvarsall.bat的解决方法
- python - web框架 - flask 代码中含有中文内容解决办法