在 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
之前收集所有结果的警告,即使是隐式的)。
考虑以下对象:
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
之前收集所有结果的警告,即使是隐式的)。