Python 多模块日志记录问题的解决方案

181 阅读2分钟

用户在使用 Python 进行多模块日志记录时遇到了问题。在不同的模块中分别编写了类和函数,并使用 logging 库进行日志记录,但只有根日志器(root logger)的日志被写入,而其他模块的日志无法正常输出。

以下是一个极简示例,其中包含了多个模块 a.py、b.py、ab.py 以及主程序 main_one.py:

# a.py
import logging

logger = logging.getLogger(__name__)

class A(object):
    def __init__(self):
        logger.debug("Instance of A")


# b.py
import logging

logger = logging.getLogger(__name__)

class B(object):
    def __init__(self):
        logger.debug("Instance of B")


# ab.py
import a
import b
import logging

logger = logging.getLogger(__name__)

class AB(a.A, b.B):
    def __init__(self):
        logger.debug("Instance of AB")
        a.A.__init__(self)
        b.B.__init__(self)


# main_one.py
import sys
import ab

import logging
import logging.handlers

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler(stream=sys.stderr)
handler.setLevel(logging.DEBUG)
handler.setFormatter(logging.Formatter('%(name)s: %(message)s'))
logger.addHandler(handler)

logger.warning("The trouble starts")

ab = ab.AB()

用户已经尝试了多种方法,例如在每个类中使用单独的日志器,但仍然无法解决问题。

解决方案

  1. 确保模块层次结构合理

确保模块层次结构合理,以便 name 属性能够正确反映模块的位置。例如,如果将模块放在不同的目录中,则 name 将是一个带有句点的分层值。

以下是一个示例,其中模块层次结构组织良好:

main_one.py
  lib/
    __init__.py
    ab.py
    basic/
      __init__.py
      a.py
      b.py
  1. 在所有模块中使用相同的日志器名称

在所有模块中使用相同的日志器名称,以便日志能够正确地聚合到一起。在示例中,可以在 main_one.py 中使用以下代码来创建日志器:

logger = logging.getLogger('daniel_lib')
  1. 将日志器添加到根日志器

将日志器添加到根日志器,以便日志能够被正确地输出。在示例中,可以在 main_one.py 中使用以下代码来将日志器添加到根日志器:

logging.getLogger().addHandler(handler)
  1. 设置日志级别

设置日志级别,以便能够控制哪些日志被输出。在示例中,可以将日志级别设置为 DEBUG,以便能够输出所有日志:

logger.setLevel(logging.DEBUG)
  1. 测试代码

在做出这些改动之后,就可以测试代码并查看日志输出是否正确。如果日志输出正确,则问题就已解决。

以下是一些代码示例,演示了如何实现上述解决方案:

# main_one.py
import sys
import ab

import logging
import logging.handlers

logger = logging.getLogger('daniel_lib')
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler(stream=sys.stderr)
handler.setLevel(logging.DEBUG)
handler.setFormatter(logging.Formatter('%(name)s: %(message)s'))
logger.addHandler(handler)

logging.getLogger().addHandler(handler)

logger.warning("The trouble starts")

ab = ab.AB()
# a.py
import logging

logger = logging.getLogger('daniel_lib')

class A(object):
    def __init__(self):
        logger.debug("Instance of A")


# b.py
import logging

logger = logging.getLogger('daniel_lib')

class B(object):
    def __init__(self):
        logger.debug("Instance of B")


# ab.py
import a
import b
import logging

logger = logging.getLogger('daniel_lib')

class AB(a.A, b.B):
    def __init__(self):
        logger.debug("Instance of AB")
        a.A.__init__(self)
        b.B.__init__(self)

通过这些修改,现在可以正常地输出日志,并能够看到来自不同模块的日志。