我正在为一个依赖于第三方软件的项目实现python.logging
,该软件也使用日志(log)记录.
问题是我们想要控制台输出,而来自两者的日志(log)是双重打印的.有没有办法设置一个处理程序来"组合"子处理程序的输出?
import logging
import sys
def third_party_use():
print_log = logging.StreamHandler(stream=sys.stdout)
print_log.setLevel(logging.INFO)
print_log.name = "SubPrintLog"
print_log.setFormatter(logging.Formatter("SubPrintLog %(name)s - %(levelname)s: %(message)s"))
third_party_logger = logging.getLogger("ThirdParty")
third_party_logger.addHandler(print_log)
third_party_logger.info("I don't want this to print twice")
if __name__ == '__main__':
print_log = logging.StreamHandler(stream=sys.stdout)
print_log.setLevel(logging.INFO)
print_log.name = "MyPrintLog"
print_log.setFormatter(logging.Formatter("MyPrintLog %(name)s - %(levelname)s: %(message)s"))
logging.basicConfig(level=0, handlers=[print_log])
logger = logging.getLogger(__name__)
logger.debug("This shouldn't appear")
logger.info("This should")
logger.warning("This definitely should")
third_party_use()
logger.info("Just my stuff again")
yield 率:
MyPrintLog __main__ - INFO: This should
MyPrintLog __main__ - WARNING: This definitely should
SubPrintLog ThirdParty - INFO: I don't want this to print twice
MyPrintLog ThirdParty - INFO: I don't want this to print twice
MyPrintLog __main__ - INFO: Just my stuff again
有没有办法将MyPrintLog
设置为不复制ThirdParty
的输出(假设我们无权修改ThirdParty
的配置).我希望propagate
旗帜可以解决这个问题,但它向相反的方向流动,我们无法修改ThirdParty
)
一种"有效"的解决方案是在拨打ThirdParty
时有效地禁用MyPrintLog
:
def turn_off_console():
for idx, handler in enumerate(logger.root.handlers):
if handler.name == "MyPrintLog":
old_level = handler.level
handler.setLevel(logging.CRITICAL)
return idx, old_level
def turn_on_console(handle_index, level):
logger.root.handlers[handle_index].setLevel(level)
然后将每个访问都包装到第三方:
idx, old_level = turn_off_console()
third_party_use()
turn_on_console(idx, old_level)
这将产生正确的输出:
MyPrintLog __main__ - INFO: This should
MyPrintLog __main__ - WARNING: This definitely should
SubPrintLog ThirdParty - INFO: I don't want this to print twice
MyPrintLog __main__ - INFO: Just my stuff again
但是,这意味着我每次都必须切换记录器,这很容易出错.
编辑:已解决
class NoThirdParty(logging.Filter):
def filter(self, record):
return not record.name == "ThirdParty"
if __name__ == '__main__':
print_log = logging.StreamHandler(stream=sys.stdout)
print_log.setLevel(logging.INFO)
print_log.addFilter(NoThirdParty()) # Do Not Reproduce Third Party!
print_log.name = "MyPrintLog"
print_log.setFormatter(logging.Formatter("MyPrintLog %(name)s - %(levelname)s: %(message)s"))
...
yield 率:
MyPrintLog __main__ - INFO: This should
MyPrintLog __main__ - WARNING: This definitely should
SubPrintLog ThirdParty - INFO: I don't want this to print twice
MyPrintLog __main__ - INFO: Just my stuff again
This Solution通过将过滤器应用到第三方记录器解决了同样的问题