【发布时间】: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