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

Python多进程环境下列表append操作无效问题排查

核心问题:Python多进程中全局列表追加操作失效

问题现象

在Python多进程场景下,向全局列表ok = []追加元素e时无任何效果,但ok.append(e)的上一行print(e)能正常输出e的有效值。核心问题为列表追加操作失效,无需关注业务逻辑。

尝试过的解决方案

  • 将ok = []放在if __name__=='__main__':代码块内,触发NameError: name 'ok' is not defined错误;
  • 在some_function内使用global ok声明全局变量,问题依旧存在。

排查结果

在some_function和程序末尾打印id(ok)后发现,各进程的ok内存地址完全不同,最终主进程输出的ok列表为空。

相关代码

import time
import multiprocessing as mp

ratios1 = [1/x for x in range(1,11)]
ratios2 = [y/1 for y in range(1,11)]

x = 283
y = 436

ok = []

def some_function(x_, y_):

    list_ = [[a, b] for a in range(1, 1980 + 1) for b in range(1, 1980 + 1) if a / b == x_ / y_]
    for e in list_:
        if not e[0] in [h[0] for h in ok]:
            if not e[1] in [u[1] for u in ok]:
                print(e)
                ok.append(e)


if __name__=='__main__':

    processes = []

    if x / y in ratios1 or x / y in ratios2:
        some_function(x_=x, y_=y)
    else:

        for X_, Y_ in [

            [x, y],
            [x - 1, y], [x, y - 1], [x + 1, y], [x, y + 1],
            [x - 2, y], [x, y - 2], [x + 2, y], [x, y + 2],
            [x - 3, y], [x, y - 3], [x + 3, y], [x, y + 3]

        ]:

            p = mp.Process(target=some_function, args=(X_,Y_))
            processes.append(p)

    start = time.time()

    for p_ in processes:
        p_.start()

    for p_ in processes:
        p_.join()

    end = time.time()

    print(f"finished in {end - start} sec")
    print(ok)

运行输出

[...]                                   # 其他"e"值
[283, 433]                              # 某个"e"值
[566, 866]                              # 某个"e"值
[849, 1299]                             # 某个"e"值
[1132, 1732]                            # 某个"e"值
finished in 0.8476874828338623 sec      # 执行时间
[]                                      # 最终输出的"ok"列表

追加id打印后的输出

2489040444480
3014871358528
2324227431488
2471301880896
1803966487616
2531583073344
1665411652672
2149818113088
2330038901824
1283883998272
2498472320064
2147028311104
2509405887552
finished in 0.8341867923736572 sec
2589544128640
[]

解决方案

Python多进程模型中,每个子进程都会复制主进程的内存空间,你定义的全局列表ok在每个子进程里都是独立的副本,子进程对副本的修改不会同步到主进程或其他子进程。要解决这个问题,需要使用进程间共享的数据结构:

方案:使用multiprocessing.Manager创建共享列表

Manager可以创建跨进程共享的对象,修改后的内容会同步到所有进程。修改后的代码如下:

import time
import multiprocessing as mp

ratios1 = [1/x for x in range(1,11)]
ratios2 = [y/1 for y in range(1,11)]

x = 283
y = 436

def some_function(x_, y_, ok):
    list_ = [[a, b] for a in range(1, 1980 + 1) for b in range(1, 1980 + 1) if a / b == x_ / y_]
    for e in list_:
        # 加锁避免多进程并发修改导致数据不一致
        with ok.get_lock():
            if not e[0] in [h[0] for h in ok]:
                if not e[1] in [u[1] for u in ok]:
                    print(e)
                    ok.append(e)


if __name__=='__main__':
    # 使用Manager创建共享列表
    with mp.Manager() as manager:
        ok = manager.list()
        processes = []

        if x / y in ratios1 or x / y in ratios2:
            some_function(x_=x, y_=y, ok=ok)
        else:
            for X_, Y_ in [
                [x, y],
                [x - 1, y], [x, y - 1], [x + 1, y], [x, y + 1],
                [x - 2, y], [x, y - 2], [x + 2, y], [x, y + 2],
                [x - 3, y], [x, y - 3], [x + 3, y], [x, y + 3]
            ]:
                p = mp.Process(target=some_function, args=(X_, Y_, ok))
                processes.append(p)

        start = time.time()

        for p_ in processes:
            p_.start()

        for p_ in processes:
            p_.join()

        end = time.time()

        print(f"finished in {end - start} sec")
        print(list(ok))

关键说明

  1. 用mp.Manager().list()替代原有全局列表,创建跨进程共享的列表对象;
  2. 将共享列表作为参数传递给子进程函数,避免全局变量的副本问题;
  3. 多进程并发修改共享列表时,必须用ok.get_lock()加锁,防止数据竞争导致的异常;
  4. 最终输出时将共享列表转为普通列表(list(ok)),方便查看完整结果。

原方案无效原因

  • 把ok放在__main__块内:子进程无法直接访问主进程内存空间内的变量,触发NameError;
  • 使用global ok:子进程的global指向的是自身内存空间内的ok副本,修改不会同步到主进程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:45:32