python日志记录,将日志重定向到上下文中的文件



如何将上下文中的日志重定向到文件。如果在作用域中调用,还重定向其他模块(第三方,例如请求、numpy等(中的日志记录。

用例是我们想要集成另一个团队的算法。我们需要将算法的日志输出到额外的文件中,这样我们就可以将其提供给他们进行调试。

例如:

import some_func_3rd_party

some_func_3rd_party()  # logs will only be written to predefined handlers
logger.info("write only to predefined handlers")
with log2file("somefile.txt"):
logger.info("write to file and predefined handlers")
some_func_3rd_party()  # logs will be written to predefined handlers and to file
logger.info("write only to predefined handlers")

目前,我看不出有什么方法可以在不访问和修改根记录器的情况下实现您想要的。

如果你想要一个更有针对性的方法,你需要知道第三方库的记录器是如何配置的。

请看一下";记录来自python请求模块"的所有请求;以便更好地理解我的意思。

以下是一种可能适用于您特定情况的方法:

import contextlib
import logging
import requests
import sys
@contextlib.contextmanager
def special_logger(app_logger, log_file, log_level=logging.DEBUG):
# Get all handlers added to the app_logger.
handlers = app_logger.handlers
# Add handlers specific to this context.
handlers.append(logging.FileHandler(filename=log_file))
handlers.append(logging.StreamHandler(stream=sys.stderr))
# Get the root logger, set the logging level,
# and add all the handlers above.
root_logger = logging.getLogger()
root_logger_level = root_logger.level
root_logger.setLevel(log_level)
for handler in handlers:
root_logger.addHandler(handler)
# Yield the modified root logger.
yield root_logger
# Clean up handlers.
for handler in handlers:
root_logger.removeHandler(handler)
# Reset log level to what it was.
root_logger.setLevel(root_logger_level)
# Get logger for this module.
app_logger = logging.getLogger('my_app')
# Add a handler logging to stdout.
sh = logging.StreamHandler(stream=sys.stdout)
app_logger.addHandler(sh)
app_logger.setLevel(logging.DEBUG)
app_logger.info("Logs go only to stdout.")
# 'requests' logs go to stdout only but won't be emitted in this case
# because root logger level is not set to DEBUG.
requests.get("http://www.google.com")
# Use the new context with modified root logger.
with special_logger(app_logger, 'my_app.log') as spec_logger:
# The output will appear twice in the console because there is
# one handler logging to stdout, and one to stderr. 
# This is for demonstration purposes only.
spec_logger.info("Logs go to stdout, stderr, and file.")
# 'requests' logs go to stdout, stderr, and file.
requests.get("http://www.google.com")
app_logger.info("Logs go only to stdout.")
# 'requests' logs go to stdout only but won't be emitted in this case
# because root logger level is not set to DEBUG.
requests.get("http://www.google.com")

最新更新