Python-在多进程中使用logger对象

在Python多进程中,使用logger记录进程信息时,由于不同进程片段可能共享同一个logger对象,导致handler重复添加,造成输出异常。例如,任务task 1至task 5中,后续任务会因重复添加handler而多次输出。解决办法是在每个进程执行结束时,及时从logger中移除handler,确保正常输出。

Python-多进程中使用logger对象

多进程中使用logger对象,为了记录进程执行时的相关信息,肯定要在进程片段中创建logger对象。

示例代码如下:

#!/usr/bin/bash
# -*-coding: utf-8

import logging
import os
from multiprocessing import Pool, cpu_count


def parallel_run(count):
    logger = logging.getLogger("test")
    logger.setLevel(logging.DEBUG)
    fmt = logging.Formatter("%(name)s %(levelname)s %(asctime)s %(message)s")
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    console.setFormatter(fmt)

    file_handler = logging.FileHandler('log_path_{}.log'.format(count))
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(fmt)

    logger.addHandler(file_handler)
    logger.addHandler(console)
    logger.debug("PID[%s]: Hello world! task: %d" % (os.getpid(), count))
    logger.info("PID[%s]: Hello world! task: %d " % (os.getpid(), count))


if __name__ == "__main__":
    pool = Pool(cpu_count() + 2)
    for i in range(1, 20):
        pool.apply_async(parallel_run, args=(i,))
    print("wait for all subprocess done")
    pool.close()
    pool.join()
    print("all process done!")

如果进程池中,待执行程序数 > 当前操作系统的cpu_count。肯定会涉及到 多个不同的程序片段,先后在同一个进程PID中被执行;

后执行的进程片段和前一个进程片段,由于在同一个PID中,getLogger('test')获取的是同一个logger对象,然后重复添加了handler。每次在当前PID中执行的程序,获取相同的logger对象,然后会不停的重复添加handler。

现象如下:

在同一个PID[8296]

  • task 1 正常输出,输出期望结果

  • task 2 重复输出了2次

  • task 3 重复输出了3次

  • task 4 在其他PID中执行,所以正常输出

  • task 5 重复输出了4次

wait for all subprocess done
test INFO 2021-12-25 23:28:50,190 PID[8296]: Hello world! task: 1 
test INFO 2021-12-25 23:28:50,191 PID[8296]: Hello world! task: 2 
test INFO 2021-12-25 23:28:50,191 PID[8296]: Hello world! task: 2 
test INFO 2021-12-25 23:28:50,194 PID[8296]: Hello world! task: 3 
test INFO 2021-12-25 23:28:50,194 PID[8296]: Hello world! task: 3 
test INFO 2021-12-25 23:28:50,194 PID[8296]: Hello world! task: 3 
test INFO 2021-12-25 23:28:50,195 PID[11916]: Hello world! task: 4 
test INFO 2021-12-25 23:28:50,195 PID[8296]: Hello world! task: 5 
test INFO 2021-12-25 23:28:50,195 PID[8296]: Hello world! task: 5 
test INFO 2021-12-25 23:28:50,195 PID[8296]: Hello world! task: 5 
test INFO 2021-12-25 23:28:50,195 PID[8296]: Hello world! task: 5
...

解决方案如下:

每次进程执行结束, 及时移除handlers列表

def parallel_run(count):
	...
    for handler in logger.handlers[:]: # 复制logger.handlers  不要直接使用logger.handlers
        if handler:
            handler.close()
            logger.removeHandler(handler)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值