プロセスのクラスメンバーを更新するにはどうすればよいですか?[複製]
私は他の質問を探しましたが、この未回答の質問は、どういうわけかこの問題をカバーしていて、あまり役に立たないことがわかった唯一の質問です。また、スレッドではなくプロセスを操作するためにこれが必要です。
だから私は最初から私の問題を示すためにサンプルプログラムを書きました、あなたはそれを貼り付けることができるはずです、そしてそれは走ります:
import multiprocessing
import time
class Apple:
def __init__(self, color):
self.color = color
def thinkAboutApple(apple):
while True:
print(apple.color)
time.sleep(2)
my_apple = Apple("red")
new_process = multiprocessing.Process(target=thinkAboutApple, args=(my_apple,))
new_process.start()
time.sleep(4)
print("new: brown")
my_apple.color = "brown"
#so that the program doesn't exit after time.sleep(4)
while True:
pass
# actual output | # wanted output
red | red
red | red
new: brown | new: brown
red | brown
red | brown
これは、リンゴが同時に2色であるという奇妙な仮定にあるか、new_processのリンゴがram内の別の位置にあり、メインプロセスでリンゴから分離されていることを示しています。
したがって、問題は次のとおりです。プロセス内のアップルのポインタが同じアップルを指すようにする方法はありますか、それともすべてのプロセスのアップルのすべてのインスタンスを同じに保つためのpythonicの方法は何ですか?多くのプロセスで同じリンゴがあり、リンゴがないプロセスがさらに多い場合、それらの領域が常に同じであることを確認するにはどうすればよいですか?
回答
2 martineau
Proxy
によって使用されるクラスの特殊なバージョンをmultiprocessing.BaseManager
(文書化されていない)から派生させることができます。これmultiprocessing.managers.NamespaceProxy
は、基本クラスとは異なり、そのすべてのメソッドと属性を公開します。これは、リンクされた重複する質問に対する@ shtse8の回答に似ていますが、その方法を明確にするために投稿しています。
from multiprocessing import Process
from multiprocessing.managers import BaseManager, NamespaceProxy
import time
import types
class MyManager(BaseManager): pass # Avoid namespace pollution.
class Apple:
def __init__(self, color):
self.color = color
def Proxy(target):
""" Create a derived NamespaceProxy class for `target`. """
def __getattr__(self, key):
result = self._callmethod('__getattribute__', (key,))
if isinstance(result, types.MethodType):
def wrapper(*args, **kwargs):
self._callmethod(key, args)
return wrapper
return result
dic = {'types': types, '__getattr__': __getattr__}
proxy_name = target.__name__ + "Proxy"
ProxyType = type(proxy_name, (NamespaceProxy,), dic) # Create subclass.
ProxyType._exposed_ = tuple(dir(target))
return ProxyType
AppleProxy = Proxy(Apple)
def thinkAboutApple(apple):
while True:
print(f"apple.color: {apple.color}")
time.sleep(1)
if __name__ == '__main__':
MyManager.register('Apple', Apple, AppleProxy)
manager = MyManager()
manager.start()
my_apple = manager.Apple("red")
new_process = Process(target=thinkAboutApple, args=(my_apple,))
new_process.start()
time.sleep(2) # Allow other process to run a short while.
my_apple.color = "brown" # Change shared class instance.
time.sleep(2) # Allow other process to run at little while longer.
new_process.terminate()