1

オブジェクト インスタンスのディクショナリを と共有する際に問題が発生していますmultiprocessingdictによって共有されているを使用managerしようとしていますが、オブジェクト インスタンスをキーとして使用しようとすると、コピーされます。

import multiprocessing

class Dog():
    def __init__(self, name = "joe"):
        self.name = name
    def bark(self):
        print("woof")

mg = multiprocessing.Manager()
dt = mg.dict()
dt["a"] = 1
dt["b"] = 2
# As expected
print(dt.items()) # => [('a', 1), ('b', 2)]
dt = mg.dict()
lab = Dog("carl")
print(lab) # => <__main__.Dog instance at 0x7f8d6bb869e0>
dt[lab] = 1
# But then I don't get the ID I expect
print(dt.items()) # => [(<__main__.Dog instance at 0x7f8d6bb86908>, 1)]

これを回避する方法はオブジェクト ID をキーとして使用することだと理解していますが、なぜこのようなことが起こっているのでしょうか? オブジェクト ID を使用することは、問題に対する最善の解決策ですか? manager dict()これは、通常の非オブジェクトでは発生しないことに気付きました。

別のアプローチ

のドキュメントでManager()、問題の一部がサーバーに変更を通知していることを読んだので、コードをこれに変更しましたが、犬が参照されずにコピーされるという同じ問題がまだあります。

import multiprocessing

class Dog():
    def __init__(self, name = "joe"):
        self.name = name
    def bark(self):
        print("woof")

mg = multiprocessing.Manager()
dt = dict()
lp = mg.list()
lp.append(dt)
print(lp)
dt["a"] = 1
dt["b"] = 2
lp[0] = dt
print(lp)
dt = dict()
lab = Dog("carl")
print(lab)
pup = Dog("steve")
print(pup)
dt[lab] = 1
dt[pup] = 2
lp[0] = dt
# Their ids change again
print(lp) 
4

2 に答える 2

3

を作成するmultiprocessing.Managerと、 によって作成されたすべてのオブジェクトのホストを担当する別のサーバー プロセスが生成されますManagerDogしたがって、インスタンスを に保存するにはManager dict、インスタンスをピクルしてプロセスに送信する必要がありManagerます。もちろん、これによりプロセス内にまったく別のDogインスタンスが作成されるため、その ID は親プロセス内Managerのインスタンスの ID と一致しません。でインスタンスとしてインスタンスを作成Dogする以外に、これを回避する方法はありません。DogProxyManager

import multiprocessing
from multiprocessing.managers import SyncManager


def Manager():
    m = SyncManager()
    m.start()
    return m

class Dog():
    def __init__(self, name = "joe"):
        self.name = name
    def bark(self):
        print("woof")

SyncManager.register("Dog", Dog)

mg = Manager()
dt = dict()
lp = mg.list()
lp.append(dt)
print(lp)
dt["a"] = 1 
dt["b"] = 2 
lp[0] = dt
print(lp)
dt = dict()
lab = mg.Dog("carl")
print(lab)
pup = mg.Dog("steve")
print(pup)
dt[lab] = 1 
dt[pup] = 2 
lp[0] = dt
# Their ids don't change
print(lp) 

出力:

<__main__.Dog instance at 0x1780098>
<__main__.Dog instance at 0x177efc8>
[{<__main__.Dog instance at 0x1780098>: 1, <__main__.Dog instance at 0x177efc8>: 2}]

Dogこれにより、親プロセスのインスタンスへのすべてのアクセスが遅くなることに注意してください。これは、Managerプロセスへの IPC 呼び出しが必要になるためです。

于 2014-10-14T19:04:22.077 に答える
2

マネージャーに関するドキュメントには次のように記載されています。

dict および list プロキシ内の変更可能な値または項目への変更は、マネージャーを介して伝播されません。これは、プロキシがその値または項目がいつ変更されたかを知る方法がないためです。このようなアイテムを変更するには、変更したオブジェクトをコンテナー プロキシに再割り当てします。

複数のプロセス間の通信をmultiprocessing容易にしますが、OS が許可していないこと (別のプロセスの任意のメモリにアクセスすること) はできません。実際にManagerは、必要に応じてシリアル化されるオブジェクトのコピーで動作します。

これを回避する方法は、オブジェクト ID をキーとして使用することだと理解しています

これらのオブジェクト インスタンスを別のプロセスで取得することはできないことに注意してください。「適切な」方法は、オブジェクトを変更したときにオブジェクトを再割り当てすることです。

于 2014-10-14T18:41:16.280 に答える