Skip to content
Advertisement

multiprocessing subprocess log to separate file

My main program logs to its own log file and the sub-process should have its own log file. I replaced the logger object inside the multiprocessing process, but the logging data from the sub-process is additionally redirected to the main log file.

How can I prevent this?

The structure looks like this:

import logging
import sys
import os
from pathlib import Path
import multiprocessing
import time

import requests


class ProcessFilter(logging.Filter):
    """Only accept log records from a specific pid."""

    def __init__(self, pid):
        self._pid = pid

    def filter(self, record):
        return record.process == self._pid


def create_logger(file):
    log = logging.getLogger(__name__)
    log.setLevel(logging.DEBUG)
    log.addFilter(ProcessFilter(pid=os.getpid()))
    file_handler = logging.FileHandler(file)
    stream_handler = logging.StreamHandler(sys.stdout)
    formatter = logging.Formatter('[%(asctime)s] %(levelname)s [%(filename)s.%(funcName)s:%(lineno)d] %(message)s',
                                  datefmt='%a, %d %b %Y %H:%M:%S')
    file_handler.setFormatter(formatter)
    stream_handler.setFormatter(formatter)
    log.addHandler(file_handler)
    log.addHandler(stream_handler)
    return log


def subprocess_init():
    global log
    sub_log_file = str(Path.home()) + '/logfile_sub.log'
    log = create_logger(sub_log_file)
    do_subprocess_stuff()


def do_subprocess_stuff():
    count = 0
    while True:
        create_log("subprocess", count)
        time.sleep(5)
        count += 1


def main_tasks():
    num = 10
    while num > 0:
        create_log("main", num)
        time.sleep(5)
        num -= 1


def create_log(text, num):
    log.debug(text + " log %s", num)


if __name__ == '__main__':
    file = str(Path.home()) + '/logfile.log'
    log = create_logger(file)
    sub_process = multiprocessing.Process(target=subprocess_init, args=())
    sub_process.daemon = True
    sub_process.start()
    main_tasks()

Advertisement

Answer

I am simply translating this answer to fit multiprocessing.

import logging

class ProcessFilter(logging.Filter):
    """Only accept log records from a specific pid."""

    def __init__(self, pid):
        self._pid = pid

    def filter(self, record):
        return record.process == self._pid
import logging
import os

def create_logger(file):
    log = logging.getLogger('')  # why use this logger and not __name__ ?
    log.setLevel(logging.DEBUG)
    log.addFilter(ProcessFilter(pid=os.getpid()))  # logger wide filter
    file_handler = logging.FileHandler(file)
    stream_handler = logging.StreamHandler(sys.stdout)
    formatter = logging.Formatter('[%(asctime)s] %(levelname)s [%(filename)s.%(funcName)s:%(lineno)d] %(message)s',
                                  datefmt='%a, %d %b %Y %H:%M:%S')
    file_handler.setFormatter(formatter)
    stream_handler.setFormatter(formatter)
    log.addHandler(file_handler)
    log.addHandler(stream_handler)
    return log

NB. you can also put the filter on a specific handler

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement