您可以使用多进程
队列或管道来在进程之间共享数据。队列既适用于线程也适用于进程。当使用管道时,如果两个进程(或线程)同时尝试从管道的同一端读取或写入数据,则管道中的数据可能会损坏,因此您需要更加小心。当然,如果进程同时使用管道的不同端口,则不存在损坏的风险。
目前,您的实现每个进程都有自己的self.all_nums_list
,所以您实际上会生成三个AllNumsClass
对象:一个在主程序中,一个在p1
中,另一个在p2
中。由于进程是独立的并且不共享相同的内存空间,它们确实正在正确地附加,但对于每个进程,它们正在附加到自己的self.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.apply
和Pool.apply_async
函数。 Pool.apply
将锁定主程序,直到所有进程完成,这在某些应用程序中想要按特定顺序获取结果时非常有用。相反,Pool.apply_async
将一次性提交所有进程,并在它们完成后立即检索结果。另一个区别是我们需要在Pool.apply_async
调用后使用get
方法以获取完成进程的返回值。
mp.Queue
的类的示例。据我所知,两个进程可以同时在同一个队列对象上工作,这是可能的,因为mp.Queue
是线程/进程安全的。我认为它们能够在两个进程之间共享数据。就个人而言,我认为mp.Queue
就像是在两个进程之间共享的全局变量,但我可能是错的。 - nathancy