python多处理子进程无法访问全局变量

Posted

技术标签:

【中文标题】python多处理子进程无法访问全局变量【英文标题】:python multiprocessing child process cannot access to global variable 【发布时间】:2019-12-12 02:33:42 【问题描述】:

我创建了一个 pandas 数据框的全局变量。我希望子进程可以访问全局数据框,但似乎子进程无法获取全局变量。

data = pd.DataFrame(data = np.array([[i for i in range(1000)] for j in range(500)]))

def get_sample(i):
    print("start round ".format(i))
    sample = data.sample(500, random_state=i)
    xs = sample.sum(axis=0)
    if i < 10:
        print(data.shape())
        print(sample.iloc[:3, :3])
    print("rount returns output".format(i))
    return xs

samples = []
def collect(result):
    print("collect called with ".format(result[0][0].shape))
    global samples
    samples.extend(result)

ntasks = 1000
if __name__=='__main__':
    samples = []
    xs = pd.DataFrame()
    """sampling"""
    pool = mp.Pool(cpu_count(logical=True))
    print("start sampling, total round = ".format(ntasks))
    r = pool.map_async(get_sample, [j for j in range(ntasks)], callback=collect)
    r.wait()
    pool.close()
    pool.join()

    xs = pd.concat([sample for sample in samples], axis = 1, ignore_index=True)
    xs = xs.transpose()

    print("xs: ")
    print(xs.shape)
    print(xs.iloc[:10, :10])

全局数据框是数据。我期望在每个子进程中,函数 get_sample 可以访问数据并从数据中检索一些值。为了确保子进程可以获取数据,我在每个子进程中打印出数据的形状。问题是子进程似乎无法获取数据,因为当我运行它时,既没有打印出数据的形状,也没有打印出部分样本。

此外,我收到错误: 回溯(最近一次通话最后): 文件“sampling2c.py”,第 51 行,在 xs = pd.concat([sample for sample in samples], axis = 1, ignore_index=True) 文件“/usr/usc/python/3.6.0/lib/python3.6/site-packages/pandas/tools/merge.py”,第 1451 行,在 concat 复制=复制) init 中的文件“/usr/usc/python/3.6.0/lib/python3.6/site-packages/pandas/tools/merge.py”,第 1484 行 raise ValueError('没有要连接的对象') get_sample 函数似乎没有返回任何内容,采样失败。

但是,当我做了一个实验来测试子进程是否可以访问全局变量时,它起作用了。

df = pd.DataFrame(data = 'a':[1,2,3], 'b':[2,4,6])
df['c1'] = [1,2,1]
df['c2'] = [2,1,2]
df['c3'] = [3,4,4]

df2 = pd.DataFrame(data = 'a':[i for i in range(100)], 'b':[i for i in range(100, 200)])
l = [1, 2, 3]
Mgr = Manager()
results = []
def collect(result):
    global results
    #print("collect called with ".format(result))
    results.extend(result)

counter = 12
def sample(i):
    print(current_process())
    return df2.sample(5, random_state = i)

if __name__=='__main__':
    pool = Pool(3)
    r = pool.map_async(sample, [i for i in range(3)], callback = collect) #callback = collect
    r.wait()
for res in results:
    print(res)

每个子进程都可以访问全局变量df2。我不确定为什么子进程无法访问第一个代码块中的数据。

【问题讨论】:

multiprocessing global variable updates not returned to parent的可能重复 Multiprocessing 根据现有答案***.com/questions/659865/… 使用自己的新全局生成新进程 子进程只有每个变量的虚拟副本。父母或孩子所做的更改不会被另一方看到。 【参考方案1】:

当您使用多处理生成一个进程时,您的新进程会在生成时获得一份状态副本。

如果您想在父进程或其他同级进程之间传递数据,您可以使用共享变量或处理共享对象的服务器进程来实现。详情见sharing-state-between-processes

如果您改为使用线程,则各个线程都在相同的上下文中运行,共享所有全局变量。因此,您可以访问所有线程和主循环中的所有全局变量,而无需执行任何特殊操作。

线程和多处理都有其优点和缺点,但这不是讨论这些的地方。

【讨论】:

感谢您的回复。我尝试过共享变量方法,我使用 manager.namespace 来共享数据框。但是,共享变量有大小限制。我需要共享一个超过 3 GB 的数据帧。当我把它放到共享变量中时,出现错误“struct.error:'i'格式需要-2147483648 进一步线程化,有道理,但每个核心的线程数有限,无法有效加速。 您能告诉我更多关于如何设置服务器进程的信息吗?使用哪些库和方法来创建服务器进程? @HenryBai 我自己从未使用过它(我通常使用队列,因为我使用套接字和串行端口),但我给你的多处理链接包含一个服务器进程的示例(就在共享的下面内存条目)。

以上是关于python多处理子进程无法访问全局变量的主要内容,如果未能解决你的问题,请参考以下文章

python多处理是否通过全局标志变量安全地进行进程间信令?

nodejs 有没有可以跨进程的全局变量

Python 多进程 ValueArray应用记录

多处理全局变量更新未返回给父级

python下多进程时全局变量在子进程怎么能更新?遇到从子进程更

python中的多处理模块和修改共享的全局变量