提问者:小点点

使用python logger从非python第三方库捕获输出


我已经编写了一个Python包,它使用了日志记录模块,并广泛使用了带有Python包装器的第三方C库。我能够将自己包中的消息打印到控制台,并将它们写入文件(每个处理程序具有不同的日志记录级别)。但是,我希望在日志文件中包含第三方库打印的消息,以便查看它们的发生顺序。这是我的MWE:

import logging

# Assume no direct access to this function. (e.g. c++ library)
def third_party_function():
    print("Inside of 'third_party_function'.")

def my_helper():
    logger.debug("Inside of 'my_helper', before third party call.")
    third_party_function()
    logger.warning("Finished with third party call.")

root_logger = logging.getLogger()
root_logger.setLevel(logging.NOTSET)

logger = logging.getLogger("mylogger")

stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.WARNING)

file_handler = logging.FileHandler(filename="progress.out")
file_handler.setLevel(logging.NOTSET)

logger.addHandler(stream_handler)
logger.addHandler(file_handler)

my_helper()

目前,屏幕的输出为:

Inside of 'third_party_function'.
Finished with third party call.

以及文件的进度。输出包含

Inside of 'my_helper', before third party call.
Finished with third party call.

但是,所需的进度。out文件已被删除

Inside of 'my_helper', before third party call.
Inside of 'third_party_function'.
Finished with third party call.

似乎没有一个记录器属于这个第三方库,因为它不是用Python编写的。

我希望避免设置sys。stdout到一个文件(如此处所示),因为我希望保持一致,并始终使用日志记录模块。同一个问题的另一个答案是定义了一个自定义类,但它似乎仍然无法捕获第三方消息。


共1个答案

匿名用户

您可以暂时将标准输出从第三方函数重定向到记录器。

使用您链接的答案中的StreamToLogger类:将Python“打印”输出重定向到记录器

def wrap_third_party_function():
    stdout = sys.stdout # save for restoring afterwards
    # redirect stdout to use a logger, with INFO level
    sys.stdout = StreamToLogger(logging.getLogger("mylogger.thirdparty"), logging.INFO)
    print("start third_party_function; stdout to log")
    third_party_function()
    sys.stdout = stdout  # restore stdout
    print("done third_party_function; stdout restored")

def my_helper():
    logger.debug("Inside of 'my_helper', before third party call.")
    wrap_third_party_function()
    logger.warning("Finished with third party call.")

在控制台上,您将看到:

done third_party_function; stdout restored
Finished with third party call.

progress.out将有:

Inside of 'my_helper', before third party call.
start third_party_function; stdout to log
Inside of 'third_party_function'.
Finished with third party call.

添加格式化程序可以更容易地看到:

formatter = logging.Formatter("%(name)s %(levelname)-8s %(message)s")
stream_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)

使用此配置,progress.out显示:

mylogger DEBUG    Inside of 'my_helper', before third party call.
mylogger.thirdparty INFO     start third_party_function; stdout to log
mylogger.thirdparty INFO     Inside of 'third_party_function'.
mylogger WARNING  Finished with third party call.