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

Posted

技术标签:

【中文标题】将每个进程记录到不同的日志文件【英文标题】:Logging each process to a different log file 【发布时间】:2019-04-20 02:09:37 【问题描述】:

我是 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】:

我对 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")

【讨论】:

以上是关于将每个进程记录到不同的日志文件的主要内容,如果未能解决你的问题,请参考以下文章

Monolog:将不同通道和多个处理程序记录到分组日志文件 + 专用日志文件

多个子进程中的 Pyhtion 2.7 记录器不会将信息记录到日志文件中

Logback 将不同的消息记录到两个文件中

后台进程的日志输出到文件

Python多进程记录到共享文件

linux 如何将守护进程的日志写到自己指定的日志文件