You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多进程池apply_async调用类方法时同一PID重复输出问题

问题分析与解决方案

首先,你看到同一PID重复输出的核心原因是multiprocessing.Pool的进程复用机制——这不是bug,而是进程池的设计初衷:

为什么会重复使用同一个PID?

进程池的核心目标是减少进程创建和销毁带来的性能开销。默认情况下,Pool会创建一组(数量等于CPU核心数,可通过参数指定)工作进程,当你调用apply_async提交任务时,池会把任务分配给当前空闲的工作进程,而不是每次都新建进程。所以同一个进程会被重复用来处理多个任务,自然会输出相同的PID。

你的代码里用了while True不断提交任务,进程池里的工作进程会循环接收任务,因此同一PID会反复出现。

如何实现“每个进程仅执行一次任务”?

如果你确实需要每个任务都由全新的进程处理,有两种方案可选:

方案1:给进程池设置maxtasksperchild=1

在初始化Pool时添加maxtasksperchild=1参数,这样每个工作进程在完成一个任务后就会被销毁,池会自动创建新的进程来处理下一个任务。修改你的start方法:

def start(self):
    print 'CREATE MAIN PROCESS {}'.format(self.pid)
    # 添加maxtasksperchild=1,让每个进程只处理一个任务
    self.pool = Pool(maxtasksperchild=1)
    num = 0
    while True:
        narg = num
        self.pool.apply_async(self, args=(narg,), callback=self.log)
        num += 1
        time.sleep(2)
    self.pool.close()
    self.pool.join()

这样每次任务都会使用新的进程,PID就不会重复了。

方案2:不使用进程池,直接创建新进程

如果不需要复用进程的性能优势,也可以直接用multiprocessing.Process每次创建新进程:

import multiprocessing

def start(self):
    print 'CREATE MAIN PROCESS {}'.format(self.pid)
    num = 0
    while True:
        narg = num
        # 每次创建新Process执行任务
        p = multiprocessing.Process(target=self.gen, args=(narg,))
        p.start()
        p.join()
        # 手动调用log,需要传递子进程的返回结果
        self.log((p.pid, narg))
        num += 1
        time.sleep(2)

这种方式完全不会复用进程,每个任务都是新的PID,但进程创建销毁的开销会更大。

补充说明

你代码里的__getstate__和__setstate__方法是正确的——因为Pool在传递对象到子进程时需要序列化,而Pool对象本身不可序列化,所以你移除了self.pool属性,这个处理没问题,不需要修改。

内容的提问来源于stack exchange,提问作者Yan Tao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:14:12