繁体   English   中英

Python:如何为 multiprocessing.Pool 中的每个项目使用不同的日志文件?

[英]Python: How to use a different logfile for each item in multiprocessing.Pool?

我正在使用multiprocessing.Pool并行运行多个独立任务。 与 python 文档中的基本示例没有太大区别:

from multiprocessing import Pool

def f(x):
    return x*x

if __name__ == '__main__':
    with Pool(5) as p:
        print(p.map(f, [1, 2, 3]))

我希望每个项目都记录到一个单独的文件中。 我在我的代码库和一些第三方包中记录了来自其他模块的各种信息(它们都不支持多处理)。 所以,例如,我想要这样:

import logging
from multiprocessing import Pool

def logOnDisk(x):
    logging.info("hello world")

if __name__ == '__main__':
    with Pool() as p:
        p.map(logOnDisk, ["ping", "pong", "foo", "bar"])

在磁盘上写:

ping.log
pong.log
foo.log
bar.log

每个文件都应包含字符串“hello world”。 我如何实现这一目标?

要从工作人员内部为每个已处理的项目(传递给pool.map()的可迭代项)使用单独的日志文件,实际上不需要特定于多处理的任何内容。 但是您可以使用 Pool 的initializer()在工作人员内部设置根记录器并存储一些用于记录的元数据。 在后台, Pool(initializer)Pool(initargs)的参数最终被传递给Process(target)Process(args)以创建新的工作进程。 然后,您只需为工作人员内部使用log_on_disk()处理的每个项目交换Filehandler

import logging
import multiprocessing as mp


def log_on_disk(x):
    logger = _init_logger(file_id=x)
    logger.info(f"hello world")


def _init_logging(level=logging.INFO, mode='a'):
    fmt = logging.Formatter(
        '%(asctime)s %(processName)-10s %(name)s %(levelname)-8s --- %(message)s'
    )
    logger = logging.getLogger()
    logger.setLevel(level)
    globals()['_log_meta'] = {'mode': mode, 'fmt': fmt}


def _init_logger(file_id):
    logger = logging.getLogger()
    logger.handlers = []  # remove all handlers
    fh = logging.FileHandler(f"{file_id}.log", mode=_log_meta['mode'])
    fh.setFormatter(_log_meta['fmt'])
    logger.addHandler(fh)
    return logger


if __name__ == '__main__':

    with mp.Pool(5, initializer=_init_logging, initargs=(logging.DEBUG,)) as pool:
       pool.map(log_on_disk, ["ping", "pong", "foo", "bar"])

@Darkonaut 得到了正确的解决方案。 我误解了这个问题,因为我认为“日志记录”是一个通用的占位符模块,而不是一个实际的模块。

如果您只想要简单的方法,那么您可以这样做:

from multiprocessing import Pool

def logOnDisk(x):
    f = open(''.join(x + ".log"), "w+")
    f.write("hello world")
    f.close()

if __name__ == '__main__':
    with Pool() as p:
        p.map(logOnDisk, ["ping", "pong", "foo", "bar"])

您当然可以将 LogOnDisk 的内容移动到 logging 或 logging.info 中:

主要.py:

import logging
from multiprocessing import Pool

def logOnDisk(x):
    logging.info(x, "hello world")

if __name__ == '__main__':
    with Pool() as p:
        p.map(logOnDisk, ["ping", "pong", "foo", "bar"])

日志记录.py:

class info:
    def __init__(self, filename, log_message):
        f = open(''.join(filename + ".log"), "w+")
        f.write(log_message)
        f.close()

进一步细化会给我们:

主要.py:

from logging import logger
from multiprocessing import Pool

def logOnDisk(x):
    logger_obj = logger(x)
    logger_obj.info("hello world")

if __name__ == '__main__':
    with Pool() as p:
        p.map(logOnDisk, ["ping", "pong", "foo", "bar"])

日志记录.py:

class logger:
    def __init__(self, filename):
        self.f = open(''.join(filename + ".log"), "w+")

    def __del__(self):
        self.f.close()

    def info(self, logString):
        self.f.write(logString)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM