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