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

多进程环境下无法修改DataFrame的问题求助

多进程下DataFrame无法修改的原因与解决办法

这个问题我碰到好多次了,本质是多进程的内存隔离机制在搞鬼,我给你拆解清楚:

为什么会出现这个问题?

当你用multiprocessing.Process创建子进程时,每个子进程都会拿到父进程数据的独立副本:

  • 在Unix/Linux/macOS上是「写时复制」——子进程一开始共享父进程内存,但一旦修改数据,就会复制出自己的独立版本;
  • 在Windows上则是直接完全复制父进程的所有内存数据。

所以你的myfunction里修改的data_attrib,其实是子进程自己的私有DataFrame副本,和父进程里的原DataFrame根本不是同一个对象。子进程运行结束后,它的内存会被回收,这些修改自然不会反映到父进程的DataFrame里。

可行的解决办法

方法1:用multiprocessing.Manager创建共享DataFrame

Manager可以帮你创建跨进程共享的对象,让所有子进程操作同一个DataFrame实例。不过要注意,共享对象会有锁开销,适合小数据量场景:

import multiprocessing
import pandas as pd

# 初始化你的DataFrame
data_attrib = pd.DataFrame({'Id': [''] * len(data_attrib)})

def myfunction(i, shared_df):
    shared_df.at[i, 'Id'] = i
    print(shared_df.at[i, 'Id'])

if __name__ == '__main__':
    # 用Manager创建可共享的DataFrame
    with multiprocessing.Manager() as manager:
        shared_data = manager.list([data_attrib])[0]
        processes = []
        for i in data_attrib.index:
            pro = multiprocessing.Process(target=myfunction, args=(i, shared_data))
            pro.start()
            processes.append(pro)
        # 等待所有进程结束
        for process in processes:
            process.join()
        # 把共享对象同步回原DataFrame
        data_attrib = pd.DataFrame(shared_data)
        print(data_attrib['Id'])

方法2:进程池+结果合并(更高效)

这种方法不需要共享数据,而是让每个子进程处理后返回结果,最后在父进程里统一更新原DataFrame,性能更好,推荐用这个:

import multiprocessing
import pandas as pd

data_attrib = pd.DataFrame({'Id': [''] * len(data_attrib)})

def myfunction(i):
    # 返回索引和对应的值
    return (i, i)

if __name__ == '__main__':
    # 创建进程池(默认用CPU核心数)
    with multiprocessing.Pool() as pool:
        # 批量提交任务,获取所有结果
        results = pool.map(myfunction, data_attrib.index)
    # 把结果更新到原DataFrame
    for idx, val in results:
        data_attrib.at[idx, 'Id'] = val
    print(data_attrib['Id'])

方法3:用pandas专用并行工具(简化代码)

如果你的任务是对DataFrame做逐行/逐列处理,可以用swifter库,它会自动判断用单进程还是多进程,代码更简洁:

import pandas as pd
import swifter

data_attrib = pd.DataFrame({'Id': [''] * len(data_attrib)})

def myfunction(row):
    row['Id'] = row.name  # row.name就是当前行的索引i
    return row

# 自动并行处理
data_attrib = data_attrib.swifter.apply(myfunction, axis=1)
print(data_attrib['Id'])

额外注意事项

  • Windows系统下,多进程代码必须放在if __name__ == '__main__':代码块里,否则会触发无限创建子进程的bug,建议不管什么系统都加上;
  • 如果你的DataFrame数据量很小,多进程的启动开销反而会比单进程慢,没必要强行并行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 17:42:57