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]))
我希望每个项目都记录到一个单独的文件中。我在我的代码库和一些第三方包中记录来自其他模块的各种信息(none 它们是多处理感知的)。所以,例如,我想要这样:
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()
的可迭代项目)使用单独的日志文件,实际上不需要 multiprocessing-specific。但是你可以
可以使用 Pool 的 initializer()
在 workers 内部设置 root-loggers 并存储一些 meta-data 用于日志记录。在幕后,Pool(initializer)
和 Pool(initargs)
的参数最终被传递给 Process(target)
和 Process(args)
以创建新的 worker-processes。
然后你只需要交换 Filehandler
为每一个在 workers 中用 log_on_disk()
处理的项目。
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 得到了正确的解决方案。我误解了这个问题,因为我认为“日志记录”是一个通用的占位符模块,而不是一个实际的模块。
如果你只想要 dead-simple 方法,那么你可以这样做:
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.info:
main.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"])
logging.py:
class info:
def __init__(self, filename, log_message):
f = open(''.join(filename + ".log"), "w+")
f.write(log_message)
f.close()
进一步细化会得到:
main.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"])
logging.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)
我正在使用 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]))
我希望每个项目都记录到一个单独的文件中。我在我的代码库和一些第三方包中记录来自其他模块的各种信息(none 它们是多处理感知的)。所以,例如,我想要这样:
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()
的可迭代项目)使用单独的日志文件,实际上不需要 multiprocessing-specific。但是你可以
可以使用 Pool 的 initializer()
在 workers 内部设置 root-loggers 并存储一些 meta-data 用于日志记录。在幕后,Pool(initializer)
和 Pool(initargs)
的参数最终被传递给 Process(target)
和 Process(args)
以创建新的 worker-processes。
然后你只需要交换 Filehandler
为每一个在 workers 中用 log_on_disk()
处理的项目。
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 得到了正确的解决方案。我误解了这个问题,因为我认为“日志记录”是一个通用的占位符模块,而不是一个实际的模块。
如果你只想要 dead-simple 方法,那么你可以这样做:
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.info:
main.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"])
logging.py:
class info:
def __init__(self, filename, log_message):
f = open(''.join(filename + ".log"), "w+")
f.write(log_message)
f.close()
进一步细化会得到:
main.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"])
logging.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)