Python 2.7:在两个python脚本中使用`logging`模块时,日志显示两次 [英] Python 2.7: log displayed twice when `logging` module is used in two python scripts

查看:448
本文介绍了Python 2.7:在两个python脚本中使用`logging`模块时,日志显示两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python 2.7.

Python 2.7.

同一文件夹中的两个文件:

Two files in the same folder:

  • 首先:主脚本.
  • 第二个:自定义模块.

可以使用logging模块而不会发生任何冲突(请参见下面的输出).

Possibility to use the logging module without any clash (see output below).

import logging
from b import test_b

def test_a(logger):
    logger.debug("debug")
    logger.info("info")
    logger.warning("warning")
    logger.error("error")

if __name__ == "__main__":
    # Custom logger.
    logger = logging.getLogger("test")

    formatter = logging.Formatter('[%(levelname)s] %(message)s')
    handler = logging.StreamHandler()
    handler.setFormatter(formatter)

    logger.setLevel(logging.DEBUG)
    logger.addHandler(handler)

    # Test A and B.
    print "B"
    test_b()
    print "A"
    test_a(logger)

b.py:

import logging

def test_b():
    logging.debug("debug")
    logging.info("info")
    logging.warning("warning")
    logging.error("error")

输出:

如下所示,日志显示为两次.

python a.py
B
WARNING:root:warning
ERROR:root:error
A
[DEBUG] debug
DEBUG:test:debug
[INFO] info
INFO:test:info
[WARNING] warning
WARNING:test:warning
[ERROR] error
ERROR:test:error

有人对此有解决方案吗?

Would anyone have a solution to this?

未运行test_b()不会导致日志重复并且不会纠正日志格式(预期).

not running test_b() will cause no log duplication and correct log formatting (expected).

推荐答案

我不确定我是否理解您的情况,因为描述与输出不匹配……但我想我知道您的问题所在.

I'm not sure I understand your case, because the description doesn't match the output… but I think I know what your problem is.

文档解释:

注意:如果将处理程序附加到记录器及其一个或多个祖先,则它可能会多次发出同一条记录.通常,您不需要将一个处理程序附加到一个以上的记录器上-如果仅将它附加到记录器层次结构中最高的适当记录器上,那么它将看到所有后代记录器记录的所有事件,前提是它们的传播设置保留为True.一种常见的情况是仅将处理程序附加到根记录器,并让传播来处理其余部分.

Note: If you attach a handler to a logger and one or more of its ancestors, it may emit the same record multiple times. In general, you should not need to attach a handler to more than one logger - if you just attach it to the appropriate logger which is highest in the logger hierarchy, then it will see all events logged by all descendant loggers, provided that their propagate setting is left set to True. A common scenario is to attach handlers only to the root logger, and to let propagation take care of the rest.

常见情况"通常效果很好,但我认为您需要在测试"中附加一个自定义处理程序,而不会影响根记录器.

And that "common scenario" usually works great, but I assume you need to attach a custom handler to "test", without affecting the root logger.

因此,如果您希望在测试"上使用自定义处理程序,并且不希望其消息也发送到根处理程序,则答案很简单:关闭其propagate标志:

So, if you want a custom handler on "test", and you don't want its messages also going to the root handler, the answer is simple: turn off its propagate flag:

logger.propagate = False


仅当您调用test_b时才发生这种情况的原因是,否则,根记录器将永远不会初始化.首次登录到任何尚未配置的记录器时,它实际上会在该记录器上执行basicConfig().因此,调用logging.getLogger().info(msg)logging.info(msg)将配置根记录程序.但是不会从儿童记录器传播.


The reason this only happens if you call test_b is that otherwise, the root logger never gets initialized. The first time you log to any logger that hasn't been configured, it effectively does a basicConfig() on that logger. So, calling logging.getLogger().info(msg) or logging.info(msg) will configure the root logger. But propagating from a child logger will not.

我相信这在日志记录的HOWTO或食谱中的任何地方都有说明,都在 HOWTOs 下,但是在实际的模块文档中,它埋在 logging.log :

I believe this is explained somewhere in the logging HOWTO or cookbook, both under HOWTOs, but in the actual module docs, it's buried in the middle of a note about threading under logging.log:

注意:除非至少有一个处理程序,否则在2.7.1和3.2之前的Python版本中,不应在线程中使用委托给root记录器的上述模块级函数.在启动线程之前将其添加到root记录器. 这些便捷功能调用basicConfig(),以确保至少有一个处理程序可用; ;在早期版本的Python中,这可能(在极少数情况下)导致将处理程序多次添加到根记录器中,这反过来又可能导致针对同一事件的多个消息.

Note: The above module-level functions which delegate to the root logger should not be used in threads, in versions of Python earlier than 2.7.1 and 3.2, unless at least one handler has been added to the root logger before the threads are started. These convenience functions call basicConfig() to ensure that at least one handler is available; ; in earlier versions of Python, this can (under rare circumstances) lead to handlers being added multiple times to the root logger, which can in turn lead to multiple messages for the same event.

很容易看出您是怎么想不到的!

It's pretty easy to see how you could have missed that!

这篇关于Python 2.7:在两个python脚本中使用`logging`模块时,日志显示两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆