将每个进程记录到不同的日志文件

时间:2018-11-16 21:13:06

标签: python python-3.x

我是Python的新手,对多进程进行日志记录似乎使我感到困惑。当前使用Python 3.6.6

我创建了一个脚本来设置我的处理程序,并允许我创建唯一的日志名称(每个过程都需要此名称)或使用主日志文件。

在控制台中,我想显示警告和错误,在日志文件中,我想跟踪调试消息。

logging_config.py

import logging
import sys
import os
import pathlib

CONSOLE_FORMATER = logging.Formatter("%(levelname)s - %(message)s")
FILE_FORMATTER = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s.%(funcName)s:%(lineno)d - %(message)s'")


def getConsoleHandler():
    consoleHandler = logging.StreamHandler(sys.stdout)
    consoleHandler.setFormatter(CONSOLE_FORMATER)
    consoleHandler.setLevel(logging.WARNING)
    return consoleHandler


def getFileHandler(**kwargs):
    path = createLogDir()

    if 'logName' in kwargs:
        logFile = path + "/" + kwargs['logName'] + ".log"
    else:
        logFile = path + "/deploy-orchestrator.log"

    # fileHandler = logging.FileHandler(logFile, mode='w')
    fileHandler = logging.FileHandler(logFile)
    fileHandler.setFormatter(FILE_FORMATTER)
    fileHandler.setLevel(logging.DEBUG)
    return fileHandler


def createLogDir():
    path = f"{os.path.dirname(os.getcwd())}/logs"   # get working parent dir
    pathlib.Path(path).mkdir(exist_ok=True)  # create /logs dir, if it exists throw no errors
    return path


# if uniqueLog is set to true then a log will be made with the logger name
def getLogger(loggerName, **kwargs):
    logger = logging.getLogger(loggerName)
    logger.addHandler(getConsoleHandler())

    if 'uniqueLog' in kwargs and kwargs['uniqueLog'] is True:
        logger.addHandler(getFileHandler(logName=loggerName))
    else:
        logger.addHandler(getFileHandler())

    logger.setLevel(logging.DEBUG)
    logger.propagate = False
    return logger

对于简单的日志记录,我只需导入我的logging_config并记录我需要的任何内容。

simple_example.py

import logging_config as logs

logger = logs.getLogger(__name__)

logger.debug("This works just fine and goes into the default log file")
logger.warning("This works just fine and goes to console and the log file")

现在要解决什么问题。

multiprocess_parent.py

from multiprocessing import Process

processes = []
for child_name in children:
    process_child = ProcessChild(child_name)
    p = Process(target=process_child.worker, args=(widget))

    processes.append(p)
    p.start()

    for p in processes:
        p.join()

multiprocess_child.py

import logging_config as logs

class ProcessChild:
    logger = None

    def __init__(self, child_name):
        self.child_name = child_name
        self.logger = logging.getLogger(child_name, uniqueLog=True)  # Each child getting it's own log file

    def worker(widget):
        logger.info("This EXPLODES")

我得到的错误是ForkingPickler(file, protocol).dump(obj) TypeError: can't pickle _thread.RLock objects

它来自此行p.start()

在这种情况下,如何为每个进程分别编写日志文件?这是我最初在错误的地方创建logging_config.py的初衷吗?我这样做是为了使多个模块可以使用相同的配置。

另外要注意的是,日志文件本身是使用正确的名称正确创建的,这是每个进程尝试将其写入正确的日志文件时发生的错误。

1 个答案:

答案 0 :(得分:0)

我对使用Python进行编码也很陌生。我可能已经离开了,但是当您定义您的 worker 方法时,在您的multiprocess_child.py中,似乎没有正确调用 logger

例如,如果要以定义的方法在 ProcessChild 类下使用全局变量 logger ,则可以使用 ProcessChild.logger (请参见下文)。

logger = None

def __init__(self, child_name):
    self.child_name = child_name
    ProcessChild.logger = logging.getLogger(child_name, uniqueLog=True)

def worker(widget):
    ProcessChild.logger.info("This EXPLODES")