タスクレット (コルーチン) への書き込みアクセス権を持つ Python プロセス間でネストされたオブジェクトを共有するにはどうすればよいですか?
これは、この質問を適切に行うために私が書いたアナロジーを使用した単純化された例です。
まず、次のgreenletパッケージをインストールしてください。sudo pip install greenlet
以下の例では:
- 変数
Natureによって参照されるクラスのインスタンスhabitat - クラスのこのインスタンスに
Natureは、というインスタンス変数がありますanimals - クラスのこのインスタンスの開始中に、
Natureクラスの 8 つの異なるインスタンスが作成され、インスタンス変数Animalに追加されました。animals私が正しければ、このインスタンスNatureはネストされたオブジェクトです。 - 最後のステップとして、
liveインスタンスのインスタンス関数は、パッケージの関数Animalを使用して 1000 に達するまでランダムに切り替えます。この関数は、インスタンスのインスタンス変数の値をランダムに変更します。greenletswitch()global_counterlivelimbsAnimal
greentest.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
期待どおりに動作します。limbsandの値の変更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であるため、このメソッドと共有できることは完全に認識していましたが、実際には、プロセス間でインスタンスとクラスを共有する方法を尋ねています。NatureAnimal