在 Python 中使用期货时如何让列表对象附加值?

How to get a list object to append values when using futures in Python?

from concurrent import futures

class MyClass:
    def __init__(self):
        self.mylist = []

    def test(self, i):
        self.mylist.append(i)

myclass = MyClass()

print(myclass.mylist)

ilist = [1, 2, 3, 4]

for i in ilist:
    myclass.test(i)

print(myclass.mylist)

myclass.mylist = []
with futures.ProcessPoolExecutor() as pool:
    for null in pool.map(myclass.test, ilist):
        pass

print(myclass.mylist)

输出:

[]
[1, 2, 3, 4]
[]

为什么将 def test 中的值附加到 self.mylist 中可以在常规循环中使用,但在使用 futures 时却不行?如何在使用期货时允许追加功能?

让我们稍微调整一下程序,以便池执行的函数 returns 列表,还可以打印 MyClass 对象的地址。

from concurrent import futures

class MyClass:
    def __init__(self):
        self.mylist = []

    def test(self, i):
        print(hex(id(self)), self.mylist, i)
        self.mylist.append(i)
        return self.mylist

if __name__ == "__main__":
    myclass = MyClass()
    ilist = [1, 2, 3, 4]
    myclass.mylist = []
    with futures.ProcessPoolExecutor() as pool:
        for null in pool.map(myclass.test, ilist):
            print(f'Output of process: {null}')    
    print(f'addr: {hex(id(myclass))} , {myclass.mylist}')

给出输出

Output of process: [1]
Output of process: [2]
Output of process: [3]
Output of process: [4]
0x1b88e358860 [] 1
0x20bffa28908 [] 3
0x259844b87f0 [] 2
0x1d7546d8898 [] 4
addr: 0x20e5ebc5400 , []

如您所见,每个进程都在处理 MyClass 对象的不同副本。

现在让我们用 ThreadPoolExecutor 替换 ProcessPoolExecutor。 现在结果如下所示:

0x1a323eb5438 [] 1
0x1a323eb5438 [1] 2
0x1a323eb5438 [1, 2] 3
0x1a323eb5438 [1, 2, 3] 4
Output of process: [1, 2, 3, 4]
Output of process: [1, 2, 3, 4]
Output of process: [1, 2, 3, 4]
Output of process: [1, 2, 3, 4]
addr: 0x1a323eb5438 , [1, 2, 3, 4]

现在每个线程都在处理同一个对象。

简而言之,进程有自己的内存,进程之间不共享。