サブプロセスのログをメインプロセスから出力したい時がある。
multiprocessingのget_logger()
とloggingのQueueHandler/QueueListener
を使うときれいに実装できたのでメモ。
実装例
import logging
import multiprocessing
from logging.handlers import QueueHandler, QueueListener
# サブプロセスで動く関数
def process(i):
logger = multiprocessing.get_logger()
logger.warning(f"num {i}")
def main():
manager = multiprocessing.Manager()
# queue作成
queue = manager.Queue()
# loggerの設定
logger = multiprocessing.get_logger()
logger.setLevel("WARN")
logger.addHandler(QueueHandler(queue)) # queueに出力するようにする
console_handler = logging.StreamHandler()
console_handler.setFormatter(logging.Formatter("%(processName)s %(message)s"))
listener = QueueListener(queue, console_handler) # queueを見るようにする
listener.start()
# サブプロセス起動
logger.warning("start!")
with multiprocessing.Pool(processes=2) as pool:
results = [pool.apply_async(process, args=(i,)) for i in range(4)]
for result in results:
result.wait()
logger.warning("finish!")
listener.stop()
if __name__ == "__main__":
main()
仕組み
メインのlogger(multiprocessing.get_logger()
)にQueueHandler
を設定してログの出力先をqueueにし、QueueListener
を使ってqueueのログを標準出力に流している。