【问题标题】:Capture output from non-python third-party library with python logger使用 python logger 从非 python 第三方库捕获输出
【发布时间】:2020-09-19 06:19:29
【问题描述】:

我编写了一个 Python 包,它使用 logging 模块,并广泛使用了带有 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.

文件progress.out包含

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

但是,想要的 progress.out 文件是

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

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

我希望避免将sys.stdout 设置为文件(如here),因为我希望保持一致并始终使用logging 模块。 Another answer 为同一个问题定义了一个自定义类,但这似乎仍然没有捕捉到第三方消息。

【问题讨论】:

    标签: python logging


    【解决方案1】:

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

    使用您链接的答案中的 StreamToLogger 类:Redirect Python 'print' output to Logger

    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.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多