如何在 Python 进程之间共享嵌套对象,并对 tasklet(协程)进行写访问?
这是一个简化的例子,我只是为了正确地提出这个问题而写的一个类比;
首先请安装greenlet
包:sudo pip install greenlet
在下面的示例中:
- 变量
Nature
引用的类的实例habitat
- 这个
Nature
类的实例有一个名为的实例变量animals
- 在启动这个
Nature
类实例的同时,创建了 8 个不同的Animal
类实例并将其附加到animals
实例变量中。现在,如果我是正确的,这个实例Nature
是一个嵌套对象。 - 作为实例的最后一步
live
实例函数Animal
使用greenlet
包的switch()
函数随机切换,直到global_counter
达到1000。该live
函数随机改变实例的limbs
实例变量的值Animal
。
绿色测试.py:
import random
from greenlet import greenlet
global_counter = 0
class Animal():
def __init__(self,nature):
self.limbs = 0
nature.animals.append(self)
self.tasklet = greenlet(self.live)
def live(self,nature):
global global_counter
while True:
self.limbs = random.randint(1, 10)
global_counter += 1
if global_counter > 1000:
break
random.sample(nature.animals,1)[0].tasklet.switch(nature)
class Nature():
def __init__(self,how_many):
self.animals = []
for i in range(how_many):
Animal(self)
print str(how_many) + " animals created."
self.animals[0].live(self)
结果是:
>>> import greentest
>>> habitat = greentest.Nature(8)
8 animals created.
>>> habitat.animals[0].limbs
3
>>> greentest.global_counter
1002
按预期工作。改变limbs
and的值global_counter
(非零)
但是当我加入multiprocessing
等式时;
greentest2.py:
import random
import multiprocessing
from greenlet import greenlet
global_counter = 0
class Animal():
def __init__(self,nature):
self.limbs = 0
nature.animals.append(self)
self.tasklet = greenlet(self.live)
def live(self,nature):
global global_counter
while True:
self.limbs = random.randint(1, 10)
global_counter += 1
if global_counter > 1000:
break
random.sample(nature.animals,1)[0].tasklet.switch(nature)
class Nature():
def __init__(self,how_many):
self.animals = []
for i in range(how_many):
Animal(self)
print str(how_many) + " animals created."
#self.animals[0].live(self)
jobs = []
for i in range(2):
p = multiprocessing.Process(target=self.animals[0].live, args=(self,))
jobs.append(p)
p.start()
结果并不如预期:
>>> import greentest2
>>> habitat = greentest2.Nature(8)
8 animals created.
>>> habitat.animals[0].limbs
0
>>> greentest2.global_counter
0
limbs
和的值global_counter
都不变(零)。我认为这是因为Animal
类的实例并global_counter
没有在进程之间共享。那么如何在进程之间共享这个Nature
类的实例或这些类的实例呢?Animal
根据@noxdafox 的回答添加;
greentest3.py:
import random
import multiprocessing
from greenlet import greenlet
global_counter = multiprocessing.Value('i', 0)
class Animal():
def __init__(self,nature):
self.limbs = 0
nature.animals.append(self)
self.tasklet = greenlet(self.live)
def live(self,nature):
global global_counter
while True:
self.limbs = random.randint(1, 10)
global_counter.value += 1
if global_counter.value > 1000:
break
random.sample(nature.animals,1)[0].tasklet.switch(nature)
class Nature():
def __init__(self,how_many):
self.animals = []
for i in range(how_many):
Animal(self)
print str(how_many) + " animals created."
#self.animals[0].live(self)
jobs = []
for i in range(2):
p = multiprocessing.Process(target=self.animals[0].live, args=(self,))
jobs.append(p)
p.start()
然后结果是:
>>> import greentest3
>>> habitat = greentest3.Nature(8)
8 animals created.
>>> habitat.animals[0].limbs
0
>>> greentest3.global_counter.value
1004
我完全知道global_counter
可以与此方法共享,因为它是一个整数,但我实际上是在询问如何在进程之间共享实例Nature
和类。Animal