【问题标题】:Problems with Python's multithreading/logging modulesPython 的多线程/日志记录模块的问题
【发布时间】:2017-10-19 02:59:56
【问题描述】:

我有一个并发运行的程序,我想为每个子进程创建一个日志。我将首先描述我的设置,然后描述我面临的问题。以下是我的主要模块:

mp_handler.py:

import logging
import multiprocessing as mp

def mp_handler(target, args_list):

    # configure logs
    for args in args_list: 
        logger_id = args[0] # first arg suffices to id a process, in my case
        logger = logging.getLogger(logger_id)
        handler = logging.FileHandler(logger_id + '.log')
        logger.setLevel(logging.INFO)
        logger.addHandler(handler)

    mp.set_start_method('spawn') # bug fix, see below        

    # build each process
    for args in args_list:
        p = mp.Process(target = target, args = args)
        p.start()

mp_worker.py:

import logging
from deco_module import deco
from my_module import function_with_open_cv

@deco
def mp_worker(args):
    logger_id = arg[0]
    logger = logging.getLogger(logger_id)

    log.info("Information about process %s" % log_id)         

    # do a lot of stuff with openCV3 
    function_with_open_cv(args)       # also logs to this child's log file

deco_module.py:这个模块做了一些异常处理,我不知道它为什么会干扰,但我想我会包括它以防万一。

from functools import wraps
import logging

def deco(function):

    @wraps(function)
    def wrapper(*args):
        logger_id = *args[0]
        logger = logging.getLogger(logger_id)
        try:
            function(*args)
        except: 
            logger.info('a message in case the child fails.')

    return wrapper

现在,谈谈我的问题。我收到了这篇文章中描述的错误:https://github.com/opencv/opencv/issues/5150。因此,我在mp_handler() 中写了mp.set_start_method('spawn') 行。

然而,在调试之后,我发现该行导致logger = logging.getLogger(logger_id)mp_worker() 创建一个新的记录器,而不是在父级中创建一个记录器,即mp_handler()。我可以通过在父模块和子模块中打印hex(id(logger)) 来看到这一点,并看到内存中的位置不同。确实,正如我所说,写mp.set_start_method('fork') 避免了这个问题(这对我来说非常粗略,因为我的理解是 spawn 将为记录器创建一个新空间)。

主要问题:所以,问题是,我如何解决这样一个事实,即我需要将启动方法设置为“spawn”以用于 OpenCV,但需要将其关闭以实现模块之间的日志通信(即为了让 mp_worker 识别其正确的 logger_id 以便登录到正确的文件)?作为良好实践的一部分,我希望将所有日志配置排除在子模块和子模块之外。

次要问题:假设我忽略了我需要 OpenCV 并将方法设置为“fork”的事实。在这种情况下,我注意到function_with_open_cv() 函数中的任何 logging.info() 语句都不会进入日志!那么,假设您的建议确实涉及将其设置为分叉,那么这里的工作是什么?编辑:修复!这也是由 OpenCV 引起的。所以问题仍然存在......我如何使用生成过程而不丢失我的记录器 ID?

非常感谢!

【问题讨论】:

    标签: python opencv logging multiprocessing


    【解决方案1】:

    您不应该在进程产生之前配置日志记录,而应该在之后配置。有关如何正确执行此操作的示例,请参阅the documentation。这适用于 Python 3,但如果需要在 Python 2 下运行,可以使用logutils package,它提供了QueueListenerQueueHandler 类。

    日志记录手册包含更多与使用 multiprocessing 进行日志记录相关的示例代码。

    【讨论】:

    • 如果您详细了解这里出了什么问题,这将是一个更好的答案。
    • @SamHartman 没有理由拒绝投票。用相当简洁的方式解释线程、分叉及其交互是不可能的。
    • 我投了反对票,因为我认为你没有回答这个问题:特别是我认为问题的那一部分询问了发生了什么。不过,阅读时,我意识到 OP 只询问如何修复。在一个足够复杂的应用程序中,我认为这不是一个好的答案,但我很遗憾投反对票。没有编辑,它不会让我改变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    • 2011-05-19
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    相关资源
    最近更新 更多