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

1万+

被折叠的 条评论
为什么被折叠?



