如何避免Python多进程中子进程日志写入主进程日志文件?
解决子进程日志重复写入主日志文件的问题
问题根源是multiprocessing在fork子进程时,会完整复制主进程的内存空间,包括logging模块中已创建的Logger对象及其绑定的Handlers。你在子进程中重新调用create_logger时,获取的是同一个__name__对应的单例Logger,此时它已经继承了主进程添加的文件和控制台Handler,再加上子进程自己新增的Handler,就会导致日志同时输出到两个文件。
解决方法
在子进程初始化Logger时,先清空该Logger对象已有的所有Handlers,再添加子进程专属的Handler。直接修改create_logger函数即可实现:
import logging import sys import os from pathlib import Path import multiprocessing import time class ProcessFilter(logging.Filter): """仅接受来自特定pid的日志记录。""" def __init__(self, pid): self._pid = pid def filter(self, record): return record.process == self._pid def create_logger(file): log = logging.getLogger(__name__) # 关键:清空已有Handler,避免继承主进程的Handler导致重复输出 log.handlers.clear() log.setLevel(logging.DEBUG) log.addFilter(ProcessFilter(pid=os.getpid())) file_handler = logging.FileHandler(file) stream_handler = logging.StreamHandler(sys.stdout) formatter = logging.Formatter('[%(asctime)s] %(levelname)s [%(filename)s.%(funcName)s:%(lineno)d] %(message)s', datefmt='%a, %d %b %Y %H:%M:%S') file_handler.setFormatter(formatter) stream_handler.setFormatter(formatter) log.addHandler(file_handler) log.addHandler(stream_handler) return log def subprocess_init(): global log sub_log_file = str(Path.home()) + '/logfile_sub.log' log = create_logger(sub_log_file) do_subprocess_stuff() def do_subprocess_stuff(): count = 0 while True: create_log("subprocess", count) time.sleep(5) count += 1 def main_tasks(): num = 10 while num > 0: create_log("main", num) time.sleep(5) num -= 1 def create_log(text, num): log.debug(text + " log %s", num) if __name__ == '__main__': file = str(Path.home()) + '/logfile.log' log = create_logger(file) sub_process = multiprocessing.Process(target=subprocess_init, args=()) sub_process.daemon = True sub_process.start() main_tasks()
额外说明
- 如果你不需要在子进程中保留主进程的任何日志配置,
log.handlers.clear()是最直接的方式,确保Logger只绑定当前进程的专属Handler。 - 也可以在子进程初始化时单独清空Handler,再调用
create_logger,但修改create_logger能让函数更健壮,无论在主进程还是子进程调用都不会出现重复Handler的问题。
内容的提问来源于stack exchange,提问作者Ximi
相关产品推荐
相关产品推荐

