Python日志重复记录问题

3
我有四个文件,

  • Main.py
  • A.py
  • B.py
  • Log_System

我正在使用主文件 Main.py 来调用 A.py 和 B.py 的函数,因此现在每次调用它们时都需要记录所有信息。

所以我编写了一个名为 log_system 的脚本,为每个脚本文件(如 A.py、B.py)创建日志处理程序。

import logging

def fetchLogger(name="None") :
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)

    if (name == "None"):
        #create File for Log
        handler = logging.FileHandler('./engine_log/Generic.log')
        handler.setLevel(logging.DEBUG)
        #log format 
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        handler.setFormatter(formatter)

        #adding the handler to Logging System
        logger.addHandler(handler)
    else: 
        #create File for Log
        handler = logging.FileHandler('./engine_log/'+str(name))
        handler.setLevel(logging.DEBUG)
        #log format 
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        handler.setFormatter(formatter)
        #adding the handler to Logging System
        logger.addHandler(handler)
    return logger

如果我想在脚本文件A.py中使用日志记录,我需要编写以下代码:

import log_system 
"""Log System Building """
file_name =  'A.py'
logger = log_system.fetchLogger(file_name)

def hello():
    try:
        logger.info("excuting Hello")
    except: 
        logger.debug("something went wrong in hello")

但是我的日志文件

2017-10-18 14:59:28,695 - log_system - INFO - A.py-excuting Hello
2017-10-18 14:59:28,695 - log_system - INFO - A.py-excuting Hello
2017-10-18 14:59:28,695 - log_system - INFO - A.py-excuting Hello
2017-10-18 14:59:28,695 - log_system - INFO - A.py-excuting Hello
2017-10-18 14:59:28,695 - log_system - INFO - A.py-excuting Hello

它正在重复记录很多次....那么我该怎么办?

解决方案

logger = logging.getLogger(name)

if logger.hasHandlers(): 
    logger.handlers = []

logger.setLevel(logging.DEBUG)

#create File for Log
handler = logging.FileHandler('./engine_log/'+str(name))
handler.setLevel(logging.DEBUG)
#log format 
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
#adding the handler to Logging System
logger.addHandler(handler)

return logger

这是我如何更改我的log_system代码,所以如果我已经创建了一个日志处理程序,我只需清空处理程序列表,这样就不会创建重复记录。

我认为最可靠的方法仍然是手动复制你的消息到打印语句和logger.info()中;明确比含蓄更好。 - undefined
2个回答

12
每次调用fetch_logger函数时,它都会向记录器添加一个新的FileHandler。 每个FileHandler都会写入日志文件,导致文件中出现重复输出。

一个解决方案是调用记录器的hasHandlers方法。如果记录器上已配置任何处理程序,则此方法将返回True,然后您可以删除它们。

def fetchLogger(name="None") :
    logger = logging.getLogger(__name__)
    if logger.hasHandlers():
        # Logger is already configured, remove all handlers
        logger.handlers = []
    # Configure the logger as before.
    ...

这真是令人开悟,终于解决了我在处理这些重复的事情时遇到的问题。如果日志记录器已经有处理程序:      # 日志记录器已经配置好,移除所有处理程序      logger.handlers = []非常感谢分享,并惊讶为什么你没有更多的赞。 - undefined
为什么要这样“hack”呢?为什么我们总是需要使用logger.hasHandlers?这看起来像是日志模块中的一个bug。 - undefined

2
使用__name__变量作为日志记录器名称可能会导致重复的另一个原因。
日志记录器假定名称中的点表示父子关系。如果您已经从树的更高模块创建了一个日志记录器,则还将调用它来处理日志记录。
因此,如果您首先在'module foo'中使用logger = logger.get_logger(__name__)并向其添加处理程序,
然后在'module foo.bar'中使用another_logger = logger.get_logger(__name__)并向其添加处理程序,
您已创建了一个父级和一个子级。
在foo.bar模块中使用another_logger.info('Some text')将导致首先执行 'foo.bar'处理程序,然后是 'foo'处理程序的相同消息。

我不明白。你能解释得更清楚一些吗? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接