繁体   English   中英

Python多处理:在进程之间共享数据

[英]Python multiprocessing: sharing data between processes

我正在尝试第一次使用多重处理,并且遇到一些相当基本的问题。 我在下面有一个玩具示例,其中两个进程将数据添加到列表中:

def add_process(all_nums_class, numbers_to_add):
    for number in numbers_to_add:
        all_nums_class.all_nums_list.append(number)

class AllNumsClass:
    def __init__(self):
        self.all_nums_list = []

all_nums_class = AllNumsClass()

p1 = Process(target=add_process, args=(all_nums_class, [1,3,5]))
p1.start()

p2 = Process(target=add_process, args=(all_nums_class, [2,4,6]))
p2.start()

all_nums_class.all_nums_list

我希望这些进程之间共享all_nums_class,以便它们都可以添加到其all_nums_list中-因此结果应为

[1,2,3,4,5,6]

而不是我现在得到的是旧的

[]

有人可以建议吗? 我在名称空间上玩了些,但是还没有在这里使用。

我觉得最好在Jupyter笔记本电脑上这样做(以防万一)。

您可以使用多处理队列或管道在进程之间共享数据。 队列既是线程安全的,又是进程安全的。 使用管道时,您必须更加小心,因为如果两个进程(或线程)尝试同时从管道的同一端读取或写入管道,则管道中的数据可能会损坏。 当然,不存在同时使用管道不同端的过程造成损坏的风险。

当前,您的实现产生两个单独的进程,每个进程都有自己的 self.all_nums_list 因此,您实质上是在生成三个AllNumsClass对象:一个在您的主程序中,一个在p1 ,一个在p2 由于进程是独立的,并且不共享相同的内存空间,因此它们可以正确地追加,但是self.all_nums_list为每个进程追加到自己的self.all_nums_list中。 这就是为什么在all_nums_class.all_nums_list中打印all_nums_class.all_nums_list时,要打印主进程的self.all_nums_list这是一个空列表的原因。 为了共享数据并使进程附加到同一列表,我建议使用队列。

使用队列和流程的示例

import multiprocessing as mp

def add_process(queue, numbers_to_add):
    for number in numbers_to_add:
        queue.put(number)

class AllNumsClass:
    def __init__(self):
        self.queue = mp.Queue()
    def get_queue(self):
        return self.queue

if __name__ == '__main__':

    all_nums_class = AllNumsClass()

    processes = []
    p1 = mp.Process(target=add_process, args=(all_nums_class.get_queue(), [1,3,5]))
    p2 = mp.Process(target=add_process, args=(all_nums_class.get_queue(), [2,4,6]))

    processes.append(p1)
    processes.append(p2)
    for p in processes:
        p.start()
    for p in processes:
        p.join()

    output = [] 
    while all_nums_class.get_queue().qsize() > 0:
        output.append(all_nums_class.get_queue().get())
    print(output)

此实现是异步的,因为它不能按顺序应用。 每次运行它,您可能会得到不同的输出。

输出示例

[1、2、3、5、4、6]

[1、3、5、2、4、6]

[2,4,6,1,3,5]

[2,1,4,3,5,6]

维护结果的有序列表或无序列表的一种更简单的方法是使用mp.Pool类。 具体来说, Pool.applyPool.apply_async函数。 Pool.apply将锁定主程序,直到所有进程完成为止,如果我们希望以特定顺序获取某些应用程序的结果,这将非常有用。 相反, Pool.apply_async将立即提交所有进程,并在完成后立即检索结果。 另一个区别是,我们需要在Pool.apply_async调用之后使用get方法,以获取完成的进程的返回值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM