Основываясь на комментариях и ответе @ user2357112, в конечном итоге я использовал потоки. Поток для обработки журналов дочернего процесса (обмениваемого через очередь), при этом все еще используя Process для реальной работы.Здесь на тот случай, если кому-то понадобится нечто подобное.
В основном после добавления:
class LoggedProcess(multiprocessing.Process):
class LoggerWriter:
def __init__(self, queue):
self.queue = queue
def write(self, message):
for line in message.rstrip().splitlines():
self.queue.put(line.rstrip())
def flush(self):
pass
@staticmethod
def logged_worker(logger_queue, worker, *args, **kwargs):
import sys
sys.stdout = sys.stderr = LoggedProcess.LoggerWriter(logger_queue)
logging.basicConfig(format="%(message)s", level=logging.INFO)
try:
worker(*args, **kwargs)
except:
pass
logger_queue.put(None)
@staticmethod
def process_logger(process, logger_queue, name):
while True:
try:
if not process.is_alive():
raise EOFError()
msg = logger_queue.get(timeout=1)
if msg is None:
raise EOFError()
logging.getLogger().log(logging.INFO, f"[PROCESS {process.pid} {name}] {msg}")
except queue.Empty:
pass # timeout
except Exception:
break # queue closed
def __init__(self, target, log_name='', args=(), kwargs={}):
self.logger_queue = multiprocessing.Queue()
self.log_name = log_name
super().__init__(target=self.logged_worker, args=(self.logger_queue, target, *args), kwargs=kwargs)
def start(self):
super().start()
logger_t = threading.Thread(target=self.process_logger, args=(self, self.logger_queue, self.log_name))
logger_t.setDaemon(True)
logger_t.start()
def terminate(self):
super().terminate()
super().join()
self.logger_queue.put(None)
мы можем просто заменить p = multiprocessing.Process(target=worker)
на p = LoggedProcess(target=worker)
.Теперь журналы дочерних процессов смешиваются с регистратором родительских процессов, в этом случае получается
LOGGER: Hello from main
[PROCESS 5000 ] Hello from the multiprocessing
Я добавил некоторую дополнительную информацию о процессе, но первоначальное намерение все еще может быть выполнено, плюс теперь оно может быть дляНапример, все они помещаются в один и тот же файл журнала родительским процессом, или все, что нужно.