logging.Logger
类。但是,我不确定如何构建我的类,以便可以建立定制继承记录器所需的基础。以下是我在
logger.py
文件中目前的内容:import sys
import logging
from logging import DEBUG, INFO, ERROR
class MyLogger(object):
def __init__(self, name, format="%(asctime)s | %(levelname)s | %(message)s", level=INFO):
# Initial construct.
self.format = format
self.level = level
self.name = name
# Logger configuration.
self.console_formatter = logging.Formatter(self.format)
self.console_logger = logging.StreamHandler(sys.stdout)
self.console_logger.setFormatter(self.console_formatter)
# Complete logging config.
self.logger = logging.getLogger("myApp")
self.logger.setLevel(self.level)
self.logger.addHandler(self.console_logger)
def info(self, msg, extra=None):
self.logger.info(msg, extra=extra)
def error(self, msg, extra=None):
self.logger.error(msg, extra=extra)
def debug(self, msg, extra=None):
self.logger.debug(msg, extra=extra)
def warn(self, msg, extra=None):
self.logger.warn(msg, extra=extra)
这是主要的
myApp.py
文件:import entity
from core import MyLogger
my_logger = MyLogger("myApp")
def cmd():
my_logger.info("Hello from %s!" % ("__CMD"))
entity.third_party()
entity.another_function()
cmd()
以下是 entity.py
模块的内容:
# Local modules
from core import MyLogger
# Global modules
import logging
from logging import DEBUG, INFO, ERROR, CRITICAL
my_logger = MyLogger("myApp.entity", level=DEBUG)
def third_party():
my_logger.info("Initial message from: %s!" % ("__THIRD_PARTY"))
def another_function():
my_logger.warn("Message from: %s" % ("__ANOTHER_FUNCTION"))
当我运行主应用程序时,我会得到以下内容:
2016-09-14 12:40:50,445 | INFO | Initial message from: __THIRD_PARTY!
2016-09-14 12:40:50,445 | INFO | Initial message from: __THIRD_PARTY!
2016-09-14 12:40:50,445 | WARNING | Message from: __ANOTHER_FUNCTION
2016-09-14 12:40:50,445 | WARNING | Message from: __ANOTHER_FUNCTION
2016-09-14 12:40:50,445 | INFO | Hello from __CMD!
2016-09-14 12:40:50,445 | INFO | Hello from __CMD!
所有内容都被打印了两次,可能是我未能正确设置记录器类。
更新1
让我澄清我的目标。
(1) 我希望将主要的日志功能封装在一个单一的位置中,这样我就可以这样做:
from mylogger import MyLogger
my_logger = MyLogger("myApp")
my_logger.info("Hello from %s!" % ("__CMD"))
(2) 我计划使用CustomFormatter
和CustomAdapter
类。这一部分不需要自定义日志记录类,可以直接插入。
(3) 我可能不需要在底层日志记录器类(记录等)方面进行深度定制,拦截logger.info
、loggin.debug
等就足够了。
所以参考一下这个Python代码片段在这些论坛上已经广泛传播:
我试图找到一个甜点,既有Logger Class
,又能够使用内置函数,如分配Formatters
和Adapters
等。因此,所有内容都与logging
模块兼容。
class OurLogger(logging.getLoggerClass()):
def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
# Don't pass all makeRecord args to OurLogRecord bc it doesn't expect "extra"
rv = OurLogRecord(name, level, fn, lno, msg, args, exc_info, func)
# Handle the new extra parameter.
# This if block was copied from Logger.makeRecord
if extra:
for key in extra:
if (key in ["message", "asctime"]) or (key in rv.__dict__):
raise KeyError("Attempt to overwrite %r in LogRecord" % key)
rv.__dict__[key] = extra[key]
return rv
更新2
我创建了一个存储库,其中包含一个简单的Python应用程序,演示了一种可能的解决方案。然而,我很想改进这个应用程序。
此示例有效地演示了通过继承覆盖logging.Logger
类和logging.LogRecord
类的技术。
两个外部项目被混合到日志流中:funcname
和username
,而不使用任何Formatters
或Adapters
。
Formatters
、Handlers
、Adapters
等进行工作。这个想法是(作为一种练习)覆盖日志记录所需的部分。话虽如此,我知道这在社区中一直引起了一定程度的争议。我仍然相信有一种方法可以通过自定义类等来实现。我知道还有其他官方的方法来做到这一点。 - mbilyanovlogging
模块在自定义方面提供了许多选项。但是,如果我们想要向logging.debug()
或logging.info()
等函数添加更复杂的自定义逻辑,该怎么办呢?例如,在现有的级别逻辑之上,假设“如果今天是星期一,则不显示任何消息”。如果不劫持loggin.info()
方法并注入我们的逻辑,那么如何实现呢? - mbilyanovLogger
继承:“... findCaller应该在Logger子类中被覆盖,以用于这些用例 - 与gonvaled不同,我认为这不是一个常见的用例。面向对象编程的一点是,您可以通过子类化和覆盖来扩展现有功能以适应特殊情况。请注意,可能会有其他方法(例如使用Filter)来提供附加处理,而不是使用包装器。” - mbilyanov