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

如何在Python multiprocessing.map()中使用Value方法?解决NameError报错

问题描述

我正在测试多进程相关代码以理解其用法,但无法让multiprocessing.Value正常工作。运行代码时提示变量p不存在,请问我哪里出错了?

我的代码

from multiprocessing import Pool, Value
from ctypes import c_int
if __name__ == "__main__":
    p=Value(c_int,1)


def addone(a):
    print(a)

    with p.get_lock():
        print(p.value)
        p.value += 1
if __name__ == "__main__":
    with Pool() as po:
        po.map(addone,range(19))
    print(p.value)

报错信息

multiprocessing.pool.RemoteTraceback: 
"""
Traceback (most recent call last):
  File "C:\Users\(I removed this)\AppData\Local\Programs\Python\Python39\lib\multiprocessing\pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
  File "C:\Users\(I removed this)\AppData\Local\Programs\Python\Python39\lib\multiprocessing\pool.py", line 48, in mapstar
    return list(map(*args))
  File "C:\Users\(I removed this)\Desktop\Python\make\multiTest.py", line 10, in addone
    with p.get_lock():
NameError: name 'p' is not defined
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File (I removed this), line 15, in <module>
    po.map(addone,range(19))
  File "C:\Users\(I removed this)\AppData\Local\Programs\Python\Python39\lib\multiprocessing\pool.py", line 364, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "C:\Users\(I removed this)\AppData\Local\Programs\Python\Python39\lib\multiprocessing\pool.py", line 771, in get
    raise self._value
NameError: name 'p' is not defined
问题原因与解决方法

原因

你在if __name__ == "__main__":块内定义了p,而addone函数运行在子进程中时,子进程不会执行主模块的__main__代码块,因此子进程的内存空间里根本不存在p变量,触发NameError。另外Pool默认不会主动将主进程的全局变量传递给子进程,子进程拥有独立的内存空间,无法直接访问主进程创建的Value对象。

解决方法

方法1:通过initializer传递共享变量

利用Pool的初始化参数,将共享变量注入每个子进程的全局空间:

from multiprocessing import Pool, Value
from ctypes import c_int

def init_worker(shared_p):
    global p
    p = shared_p

def addone(a):
    print(a)
    with p.get_lock():
        print(p.value)
        p.value += 1

if __name__ == "__main__":
    p = Value(c_int, 1)
    with Pool(initializer=init_worker, initargs=(p,)) as po:
        po.map(addone, range(19))
    print(p.value)
  • initializer指定子进程启动时执行的初始化函数,initargs是传递给该函数的参数。
  • 在初始化函数里把共享变量赋值给子进程的全局p,让addone能正常访问。

方法2:使用Manager创建可传递的共享变量

Manager创建的共享对象可以直接作为参数传递给子进程函数,适配Pool的使用场景:

from multiprocessing import Pool, Manager
from ctypes import c_int

def addone(a, shared_p):
    print(a)
    with shared_p.get_lock():
        print(shared_p.value)
        shared_p.value += 1

if __name__ == "__main__":
    with Manager() as manager:
        p = manager.Value(c_int, 1)
        with Pool() as po:
            # 用starmap传递多个参数
            po.starmap(addone, [(num, p) for num in range(19)])
        print(p.value)
  • Manager.Value创建的共享变量支持跨进程传递,可直接作为函数参数传入。
  • 因为map只能传递单个参数,所以改用starmap来传递包含多个参数的元组列表。

关键注意点

  • 操作共享变量时必须加锁(get_lock()),防止多个进程同时修改引发数据竞争,导致结果异常。
  • Windows系统下多进程采用spawn启动方式,子进程会重新导入主模块,因此主逻辑必须放在if __name__ == "__main__":块内,这一点你已经处理正确。

内容的提问来源于stack exchange,提问作者ok yes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:10:38