[英]extending logging.Logger module in python 3.5
我一直試圖通過logging.Logger
來創建一個新的Logger
類。 Python版本是3.5
我的應用程序中有幾個模塊,我只在主模塊中配置日志記錄,我使用logging.setLoggerClass(...)
設置logger類
但是,當我從其他模塊中檢索相同的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")
當執行該代碼,我期望applogger
在模塊2為類型MyLoggerClass
。 我打算使用new_logger_method
來實現一些新功能。
但是,由於applogger
變成了類型logging.Logger
,當代碼運行時它會拋出Logger
沒有名為new_logger_method
屬性。
有沒有人遇到過這個問題?
在此先感謝您的幫助! Pranav
通過更改默認記錄器工廠來嘗試影響全局logger
器,如果您希望模塊可以很好地適應任何環境,則應該為您的模塊(及其子代)定義一個記錄器,並將其用作其他所有內容的主記錄器更深入的模塊結構。 問題是您明確要使用與默認/全局定義的不同的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
中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'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.