在 python 多处理中更改对象属性

Changing object properties in python multiprocessing

考虑以下对象:

class Item(object):
    def __init__(self):
        self.c = 0
    def increase(self):
        S.increase(self)

class S(object):
    @staticmethod
    def increase(item):
        item.c += 1

这反映了我目前所处的情况,S 是某个库 class,Item 收集和组织数据以及数据操作过程。现在我想并行化工作,为此我使用 python 多处理模块:

from multiprocessing import Process
l= [Item() for i in range(5)]
for i in l:
    Process(target=i.increase).start()

结果不是我所期望的:

[i.c for i in l]
[0, 0, 0, 0, 0]

我哪里错了?

您期待您的增变器,class S 中的静态方法 increase(从 class 中的非静态 increase 调用item) 来调整每个 i.c 字段——确实如此。问题不在于静态方法,而在于 multiprocessing.

的内部设计

multiprocessing 包由 运行 个 Python 的多个单独实例运行。在类 Unix 系统上,它使用 fork,这使得这更容易;在类似 Windows 的系统上,它会生成自己的新副本。无论哪种方式,这都会施加 Python 文档中描述的所有稍微奇怪的限制:v2 and v3。 (注意:下面的其余链接指向 Python2 文档,因为那是我仍然打开的页面。Python2 和 Python 的限制几乎相同3.)

在这种特殊情况下,每个 Process 调用都会生成对象的副本 i 并将该副本发送到新进程。进程修改副本,对原件没有影响

要解决此问题,您可以将修改后的对象发回,例如,通过 Queue() or Pipe() instance, or place the objects into shared memory。发回技术更简单,更易于编程,并自动执行大部分必要的同步(但请参阅关于确保在使用 Process 实例的 join 之前收集所有结果的警告,即使是隐式的)。