【问题标题】:logging with the same logging levels across modules跨模块使用相同的日志记录级别进行日志记录
【发布时间】:2018-10-15 18:08:58
【问题描述】:

我对 Python 有点陌生,尤其是在多个文件中编写模块和函数,而不仅仅是原始脚本。

我正在编写一个命令行应用程序,我想要一个函数(我称之为argpconf)来解析命令行参数并相应地设置日志级别。最重要的是,我希望在此函数中设置一次日志级别,并且在创建记录器时以最小开销在所有模块中保持相同。此外,我希望能够在使用通用格式化程序时识别消息来自的模块:

logging.Formatter("%(levelname)s : %(name)s : %(message)s")

部分基于a cookiecutter template,我创建了以下文件:

├── api
│   ├── __init__.py
│   └── some_functionality.py
├── cli.py
├── core
│   ├── argpconf.py
│   ├── __init__.py
│   ├── logger.py
│   └── __version__.py
├── __init__.py
└── __main__.py

core/logger.py有以下内容:

from logging import Formatter, Logger as _Logger, NullHandler, StreamHandler

class Logger(_Logger):
    def __init__(self, name=None):
        super(Logger, self).__init__(name or __name__.split(".")[0])
        self.addHandler(NullHandler())  # default to no output
    def start(self, level="WARN", stream=None,
              fmt="%(levelname)s : %(name)s : %(message)s"):
        handler = StreamHandler(stream)
        handler.setFormatter(Formatter(fmt))
        self.addHandler(handler)
        self.setLevel(level.upper())
    def stop(self):
        for handler in self.handlers[1:]:
            # Remove everything but the NullHandler.
            self.removeHandler(handler)

logger = Logger()

与这些问题的答案中建议的想法相比:

我真的很喜欢 cookiecutter 模板中使用记录器的方法,因为它只允许您使用 import logger 并拥有一个 logger 对象,它的日志级别在所有模块中都是相同的。但是,我对此并不完全满意,因为在我的情况下,argpconf.py 是第一个启动 logger 的模块,因此来自所有模块的所有日志消息都将其 %(name)s 替换为 core,因为它是 @987654337 @的__name__.split(".")[0]

如何改进logger 模块,以便它检测调用它的模块并打印带有%(name)s 模块的日志消息,甚至打印它们的函数?

【问题讨论】:

  • logging.basicConfig(level=LOGLEVEL) 不满足您的需求吗?
  • 我用示例代码的链接更新了我的答案(有点太多代码要内联添加到答案中)。

标签: python logging


【解决方案1】:

这种方法似乎使事情变得比需要的更复杂。我意识到这来自您使用的 cookiecutter 模板,这只是我的意见,但在该模板中采用的日志记录方法并不是我认为的最佳实践。你最了解你的用例,但如果我想要的只是

有一个函数可以解析命令行参数并相应地设置日志级别。最重要的是,我希望在此函数中设置一次日志级别,并且在创建记录器时以最小开销在所有模块中保持相同。此外,我希望能够在使用通用格式化程序时识别消息来自的模块

那么最简单的方法是在您的主脚本中导入argparselogging,处理命令行参数并相应地设置日志记录级别,调用basicConfig()(如Brian M. Sheldon 的评论中所建议)然后调度到您的应用程序端点,由命令行参数确定。您使用的每个需要记录某些内容的模块只需要到 import logginglogger = logging.getLogger(__name__) 然后 logger.debug(...) 或其他任何地方,只要该模块需要。如果你坚持这一点,所有模块将自动使用basicConfig()中设置的日志级别,如果你在format=参数中使用片段%(name)sbasicConfig(),那么你将在其中看到完整的模块名称放置在记录的消息中,作为完全限定的点名称(如api.some_functionality)。与 cookiecutter 模板相比,这种方法在创建记录器方面的开销肯定会更少。

更新:我将通过一个示例更新Python Logging Cookbook。现在,here's a Gist 只需要代码。

【讨论】:

  • 听起来不错,但我不确定我是否完全理解。请您添加一些示例代码吗?
猜你喜欢
  • 1970-01-01
  • 2011-10-21
  • 2014-12-27
  • 2013-03-26
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多