gpt4 book ai didi

python - 在 python 3.5 中扩展 logging.Logger 模块

转载 作者:行者123 更新时间:2023-11-28 17:06:54 25 4
gpt4 key购买 nike

我一直在尝试通过继承 logging.Logger 来创建一个新的 Logger 类。 Python版本为3.5

我的应用程序中有几个模块,我只在主模块中配置日志记录,我在主模块中使用 logging.setLoggerClass(...)

设置记录器类

但是,当我从其他模块检索相同的 Logger 实例时,它仍然会创建 Logger 类的新实例,而不是我定义的子类实例。

例如我的代码是:

# module 1
import logging
class MyLoggerClass(logging.getLoggerClass()):
def __init__(name):
super(MyLoggerClass, self).__init__(name)

def new_logger_method(...):
# some new functionality

if __name__ == "__main__":
logging.setLoggerClass(MyLoggerClass)
mylogger = logging.getLogger("mylogger")
# configuration of mylogger instance

# module 2
import logging
applogger = logging.getLogger("mylogger")
print(type(applogger))
def some_function():
applogger.debug("in module 2 some_function")

执行此代码时,我希望模块 2 中的 apploggerMyLoggerClass 类型。我打算使用 new_logger_method 来实现一些新功能。

然而,由于 applogger 结果是 logging.Logger 类型,当代码运行时它抛出 Logger has no attribute named new_logger_method

有没有人遇到过这个问题?

在此先感谢您的帮助!普拉纳夫

最佳答案

与其尝试通过更改默认记录器工厂来影响全局记录器,如果您希望您的模块在任何环境中都能很好地运行,您应该只为您的模块(及其子模块)定义一个记录器并将其用作模块结构中其他所有内容的主要记录器。问题在于您明确希望使用与默认/全局定义类不同的 logging.Logger 类,并且 logging 模块没有提供一种简单的方法来执行上下文- 基于工厂切换,所以你必须自己做。

有很多方法可以做到这一点,但我个人的偏好是尽可能明确并定义您自己的 logger 模块,然后您可以在需要时将其导入包中的其他模块获取自定义记录器。在您的情况下,您可以在包的根目录创建 logger.py 并执行如下操作:

import logging

class CustomLogger(logging.Logger):

def __init__(self, name):
super(CustomLogger, self).__init__(name)

def new_logger_method(self, caller=None):
self.info("new_logger_method() called from: {}.".format(caller))

def getLogger(name=None, custom_logger=True):
if not custom_logger:
return logging.getLogger(name)
logging_class = logging.getLoggerClass() # store the current logger factory for later
logging._acquireLock() # use the global logging lock for thread safety
try:
logging.setLoggerClass(CustomLogger) # temporarily change the logger factory
logger = logging.getLogger(name)
logging.setLoggerClass(logging_class) # be nice, revert the logger factory change
return logger
finally:
logging._releaseLock()

如果您愿意,可以随意在其中包含其他自定义日志初始化逻辑。然后,您可以从其他模块(和子包)导入此记录器并使用其 getLogger() 获取本地自定义记录器。例如,module1.py 中您需要的是:

from . import logger  # or `from package import logger` for external/non-relative use

log = logger.getLogger(__name__) # obtain a main logger for this module

def test(): # lets define a function we can later call for testing
log.new_logger_method("Module 1")

这涵盖了内部使用 - 只要您在所有模块/子模块中坚持这种模式,您就可以访问您的自定义记录器。

当涉及到外部使用时,您可以编写一个简单的测试来向您展示您的自定义记录器已创建并且它不会干扰记录系统的其余部分,因此您的包/模块可以被声明为好公民。假设您的 module1.py 位于名为 package 的包中,并且您想从外部对其进行整体测试:

import logging  # NOTE: we're importing the global, standard `logging` module
import package.module1

logging.basicConfig() # initialize the most rudimentary root logger
root_logger = logging.getLogger() # obtain the root logger
root_logger.setLevel(logging.DEBUG) # set root log level to DEBUG

# lets see the difference in Logger types:
print(root_logger.__class__) # <class 'logging.RootLogger'>
print(package.module1.log.__class__) # <class 'package.logger.CustomLogger'>

# you can also obtain the logger by name to make sure it's in the hierarchy
# NOTE: we'll be getting it from the standard logging module so outsiders need
# not to know that we manage our logging internally
print(logging.getLogger("package.module1").__class__) # <class 'package.logger.CustomLogger'>

# and we can test that it indeed has the custom method:
logging.getLogger("package.module1").new_logger_method("root!")
# INFO:package.module1:new_logger_method() called from: root!.
package.module1.test() # lets call the test method within the module
# INFO:package.module1:new_logger_method() called from: Module 1.

# however, this will not affect anything outside of your package/module, e.g.:
test_logger = logging.getLogger("test_logger")
print(test_logger.__class__) # <class 'logging.Logger'>
test_logger.info("I am a test logger!")
# INFO:test_logger:I am a test logger!
test_logger.new_logger_method("root - test")
# AttributeError: 'Logger' object has no attribute 'new_logger_method'

关于python - 在 python 3.5 中扩展 logging.Logger 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50398444/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com