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

Python multiprocessing运行时main()前代码重复执行问题

现象产生原因

macOS 下 Python 3.8+ 版本的multiprocessing模块默认使用spawn方式启动子进程,Windows 系统也始终使用该启动模式。spawn模式不会像Linux默认的fork模式那样直接复制父进程的内存状态,而是会启动一个全新的Python解释器进程,重新导入主程序模块完成初始化。

你当前代码中,列表生成、print("hello\n")这类逻辑全部写在了主模块的顶层,没有放在if __name__ == "__main__":判断块内。子进程导入主模块时,这些顶层代码会被逐行执行:主进程启动时执行1次,你开了4个工作进程就会额外执行4次,总共打印5次hello,和你终端的输出完全吻合。
这种模式下如果顶层有文件写入、数据库连接、随机数生成这类逻辑,还会出现资源重复占用、子进程数据和主进程不一致等隐蔽bug。

跨平台多进程开发最佳实践
  • 所有仅需主进程执行的逻辑:包括全局变量初始化、配置加载、测试打印、进程池创建、任务调度代码,必须全部放在if __name__ == "__main__":判断块内部,或者放在被该块调用的入口函数中,绝对不要裸露在模块顶层。
  • 不要依赖全局变量给子进程传参:spawn模式下子进程的全局变量是重新导入模块生成的独立副本,和主进程的变量不共享,所有任务需要的参数必须通过Pool的map/starmap等方法显式传递。如果需要多进程共享状态,使用multiprocessing提供的Queue、Value、Array、Manager等专门的跨进程通信结构。
  • 显式指定进程启动方式:在入口代码最开头、创建任何进程/进程池之前,调用multiprocessing.set_start_method("spawn")统一全平台的进程启动行为,避免不同操作系统默认启动方式差异导致的诡异问题。注意该方法在整个程序生命周期中只能调用一次。
修正后的main.py参考代码
from multiprocessing import Pool, set_start_method
from simulator.simulation import a_simulation
import random

def main():
    num_trials = 10
    iter_trials = list(range(num_trials))
    arg_list = [random.random() for _ in range(num_trials)]
    input_args = list(zip(iter_trials, arg_list))

    print("hello\n")

    with Pool(processes=4) as pool:
        result = pool.starmap(a_simulation, input_args)
        print(result)


if __name__ == "__main__":
    set_start_method("spawn")
    main()

运行修正后的代码,hello只会在主进程启动时打印1次,不会再出现重复执行顶层逻辑的问题。


内容的提问来源于stack exchange,提问作者G. Z.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 04:09:25