用Python的logging模块记录日志时,遇到了重复记录日志的问题,第一条记录写一次,第二条记录写两次,第三条记录写三次。。。很头疼,这样记日志可不行。网上搜索到了原因与解决方案:

原因:没有移除handler
解决:在日志记录完之后removeHandler

修改前示例代码:

import logging

def log(message):
logger = logging.getLogger('testlog') streamhandler = logging.StreamHandler()
streamhandler.setLevel(logging.ERROR)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s')
streamhandler.setFormatter(formatter) logger.addHandler(streamhandler)
logger.error(message) if __name__ == '__main__':
log('hi')
log('hi too')
log('hi three')

修改前输出结果:

2016-07-08 09:17:29,740 - ERROR - testlog - hi
2016-07-08 09:17:29,740 - ERROR - testlog - hi too
2016-07-08 09:17:29,740 - ERROR - testlog - hi too
2016-07-08 09:17:29,740 - ERROR - testlog - hi three
2016-07-08 09:17:29,740 - ERROR - testlog - hi three
2016-07-08 09:17:29,740 - ERROR - testlog - hi three

修改后示例代码:

import logging

def log(message):
logger = logging.getLogger('testlog') streamhandler = logging.StreamHandler()
streamhandler.setLevel(logging.ERROR)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s')
streamhandler.setFormatter(formatter) logger.addHandler(streamhandler)
logger.error(message) # 添加下面一句,在记录日志之后移除句柄
logger.removeHandler(streamhandler) if __name__ == '__main__':
log('hi')
log('hi too')
log('hi three')

修改后输出结果:

2016-07-08 09:32:28,206 - ERROR - testlog - hi
2016-07-08 09:32:28,206 - ERROR - testlog - hi too
2016-07-08 09:32:28,206 - ERROR - testlog - hi three

深度解析:

Google之后,大概搞明白了,就是你第二次调用log的时候,根据getLogger(name)里的name获取同一个logger,而这个logger里已经有了第一次你添加的handler,第二次调用又添加了一个handler,所以,这个logger里有了两个同样的handler,以此类推,调用几次就会有几个handler。。

所以这里有以下几个解决办法:

  1. 每次创建不同name的logger,每次都是新logger,不会有添加多个handler的问题。(ps:这个办法太笨,不过我之前就是这么干的。。)
  2. 像上面一样每次记录完日志之后,调用removeHandler()把这个logger里的handler移除掉。
  3. 在log方法里做判断,如果这个logger已有handler,则不再添加handler。
  4. 与方法2一样,不过把用pop把logger的handler列表中的handler移除。

下面是方法3与方法4的代码示例:

方法3:

import logging

def log(message):
logger = logging.getLogger('testlog') # 这里进行判断,如果logger.handlers列表为空,则添加,否则,直接去写日志
if not logger.handlers:
streamhandler = logging.StreamHandler()
streamhandler.setLevel(logging.ERROR)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s')
streamhandler.setFormatter(formatter)
logger.addHandler(streamhandler) logger.error(message) if __name__ == '__main__':
log('hi')
log('hi too')
log('hi three')

方法4:

import logging

def log(message):
logger = logging.getLogger('testlog') streamhandler = logging.StreamHandler()
streamhandler.setLevel(logging.ERROR)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s')
streamhandler.setFormatter(formatter) logger.addHandler(streamhandler) logger.error(message) # 用pop方法把logger.handlers列表中的handler移除,注意如果你add了多个handler,这里需多次pop,或者可以直接为handlers列表赋空值
logger.handlers.pop()
# logger.handler = [] if __name__ == '__main__':
log('hi')
log('hi too')
log('hi three')

 

python logging 重复写日志问题的更多相关文章

  1. 解决python logging重复写日志问题

    import logging from homework.exam_homework_0413.common import contants from homework.exam_homework_0 ...

  2. Python Logging模块 输出日志颜色、过期清理和日志滚动备份

    # coding:utf-8 import logging from logging.handlers import RotatingFileHandler # 按文件大小滚动备份 import co ...

  3. [已解决] Python logging 重复打印日志信息

    问题描述 问题代码如下: def get_logger(logger_name): """得到日志对象""" logger = loggin ...

  4. 0x03 Python logging模块之Formatter格式

    目录 logging模块之Formatter格式 Formater对象 日志输出格式化字符串 LogRecoder对象 时间格式化字符串 logging模块之Formatter格式 在记录日志是,日志 ...

  5. python找寻合适的日志库logging Handler——Handler自定义实现

    最近在用python tornado开发一个app的服务端.投产的系统肯定需要包含日志功能,这里就自然想到了用python自带的logging库.   logging中日志内容的输出都交由Handle ...

  6. python中利用logging包进行日志记录时的logging.level设置选择

    之前在用python自带的logging包进行日志输出的时候发现有些logging语句没有输出,感到比较奇怪就去查了一下logging文档.然后发现其在设置和引用时的logging level会影响最 ...

  7. python logging 日志轮转文件不删除问题

    前言 最近在维护项目的python项目代码,项目使用了 python 的日志模块 logging, 设定了保存的日志数目, 不过没有生效,还要通过contab定时清理数据. 分析 项目使用了 logg ...

  8. Python同时向控制台和文件输出日志logging的方法 Python logging模块详解

    Python同时向控制台和文件输出日志logging的方法http://www.jb51.net/article/66756.htm 1 #-*- coding:utf-8 -*- 2 import ...

  9. Python logging日志系统

    写我小小的日志系统 配置logging有以下几种方式: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数: 2)创建一个日志配置文件, ...

随机推荐

  1. Strategy(策略)

    意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换.本模式使得算法可独立于使用它的客户而变化. 适用性: 许多相关的类仅仅是行为有异.“策略”提供了一种用多个行为中的一个行为来配置 ...

  2. Android安装包apk文件在某些版本操作系统上安装解析包出错问题的解决办法

    当我们将Android升级功能的中的下载新版本apk文件存放在data/data/xxx.apk位置时,在有的些版本的手机中安装可能会出现安装包解析出错的问题,对于该问题的解决方案是提升该文件的权限. ...

  3. Java回顾之集合

    在这篇文章里,我们关注Java中的集合(Collection).集合是编程语言中基础的一部分,Java自JDK早期,就引入了Java Collection Framework.设计JCF的那个人,后来 ...

  4. Java Spring-Bean

    2017-11-06 18:59:30 Bean初始化和销毁方法 配置初始化和销毁的方法:* init-method=”setup”* destroy-method=”teardown”执行销毁的时候 ...

  5. bzoj2705: [SDOI2012]Longge的问题 欧拉定理

    题意:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N). 题解:考虑n的所有因子,假设有因子k,那么对答案的贡献gcd(i,n)==k的个数即gcd(i/k,n/k)== ...

  6. Codeforces Round #415 (Div. 2)C

    反正又是一个半小时没做出来... 先排序,然后求和,第i个和第j个,f(a)=a[j]-a[i]=a[i]*(2^(j-i-1))因为从j到i之间有j-i-1个数(存在或者不存在有两种情况) 又有a[ ...

  7. IOS-常用第三方开源框架介绍

    iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角) 时间:2015-05-06 16:43:34      阅读:533      评论:0      收藏:0      [点我收藏+] ...

  8. 《剑指offer》习题解答(C/C++)

    1.二维数组中的查找 /* 题目:在一个二维数组中,没一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序. 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  9. POJ 3279 Filptile dfs

    题目链接:http://poj.org/problem?id=3279 大意:给出一块n*m的棋盘.里面放满了棋子.有1和0两种状态.给出初始状态,翻动的时候会把当前位置和当前位置的上下左右共五个位置 ...

  10. 获得文件路径 _pgmptr, _makepath, _splitpath

    #include <stdlib.h> #include <stdio.h> int main(void) { char path_buffer[_MAX_PATH]; cha ...