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

Python多进程作用域在两台机器表现不同:为何无法访问__main__变量?

问题原因分析

这种差异源于Python多进程的启动方式差异:

  • Linux(Ubuntu)默认使用fork启动方式:fork会直接复制父进程的完整内存空间,包括所有全局变量、模块导入状态等,因此子进程能直接访问主进程中定义的arr变量。
  • macOS从Python 3.8开始默认改用spawn启动方式:spawn会启动全新的Python解释器进程,重新导入主模块。此时主模块中只有if __name__ == '__main__':块内的代码不会重复执行,而arr恰好定义在这个代码块里,导致子进程的命名空间中不存在arr变量,触发NameError。
解决方案

针对这个问题,有几种可靠的解决方法:

方法1:将变量作为参数传递给子进程函数

这是最规范的做法,避免依赖进程间的隐式内存共享:

import multiprocessing
import os
import numpy as np
import time
from functools import partial

def mapping_func(arr, idx):
    a = arr[idx]
    time.sleep(1)
    print(a)
    return a

if __name__ == '__main__': 
    arr = np.linspace(0, 20, 11)
    # 用partial绑定arr参数
    func_with_arr = partial(mapping_func, arr)
    
    with multiprocessing.Pool(os.cpu_count()) as pool:
        pooled = pool.map(func_with_arr, np.arange(len(arr)))

也可以用pool.starmap直接传递多参数:

# 其余代码不变
if __name__ == '__main__': 
    arr = np.linspace(0, 20, 11)
    # 构造包含(arr, idx)的元组列表
    args_list = [(arr, idx) for idx in np.arange(len(arr))]
    
    with multiprocessing.Pool(os.cpu_count()) as pool:
        pooled = pool.starmap(mapping_func, args_list)

方法2:强制使用fork启动方式(仅适用于非GUI场景)

如果程序不需要和GUI交互,可以在macOS上强制切换回fork启动方式:

import multiprocessing
import os
import numpy as np
import time

def mapping_func(idx):
    a = arr[idx]
    time.sleep(1)
    print(a)
    return a

if __name__ == '__main__': 
    # 强制设置启动方式为fork
    multiprocessing.set_start_method('fork')
    arr = np.linspace(0, 20, 11)

    with multiprocessing.Pool(os.cpu_count()) as pool:
        pooled = pool.map(mapping_func, np.arange(len(arr)))

注意:macOS的GUI框架(如Tkinter、PyQt)不兼容fork方式,会导致程序崩溃,此类场景请勿使用该方法。

方法3:使用共享内存(适合大数据场景)

如果arr是超大数组,传递副本效率低下,可以用multiprocessing的共享内存机制:

import multiprocessing
import os
import numpy as np
import time

def mapping_func(idx, arr_shared):
    # 将共享内存转为numpy数组
    arr = np.frombuffer(arr_shared.get_obj(), dtype=np.float64)
    a = arr[idx]
    time.sleep(1)
    print(a)
    return a

if __name__ == '__main__': 
    arr = np.linspace(0, 20, 11, dtype=np.float64)
    # 创建共享内存数组
    arr_shared = multiprocessing.Array('d', arr)
    
    with multiprocessing.Pool(os.cpu_count()) as pool:
        # 传递共享内存对象和索引
        pooled = pool.starmap(mapping_func, [(idx, arr_shared) for idx in np.arange(len(arr))])

内容的提问来源于stack exchange,提问作者Brian.C.Seymour

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 05:07:34