Comment puis-je mettre à jour les membres de la classe dans les processus? [dupliquer]
J'ai cherché d'autres questions, et cette question sans réponse est la seule que j'ai pu trouver qui couvre en quelque sorte cette question et n'est pas vraiment utile. De plus, j'en ai besoin pour travailler avec des processus et non avec des threads.
Donc, à partir de zéro, j'ai écrit un exemple de programme pour montrer mon problème, vous devriez pouvoir le coller et il fonctionnera:
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
Cela me dit que soit la pomme est dans une supposition étrange où elle est de deux couleurs en même temps, soit que la pomme de new_process est dans une autre position dans la RAM et séparée de la pomme dans le processus principal.
La question est donc la suivante: y a-t-il un moyen pour que le pointeur de la pomme dans le processus pointe vers la même pomme, ou quelle est la manière pythonique de garder toutes les instances de la pomme dans tous les processus identiques? Et si j'ai la même pomme dans de nombreux processus et encore plus de processus sans la pomme, comment puis-je m'assurer qu'ils ont toujours la même surface?
Réponses
Vous pouvez dériver une version spécialisée d'une Proxy
classe utilisée par à multiprocessing.BaseManager
partir d'un (non documenté) multiprocessing.managers.NamespaceProxy
qui, contrairement à la classe de base, expose toutes ses méthodes et attributs. Ceci est similaire à la réponse de @ shtse8 à la question en double liée, mais je la poste pour expliquer clairement comment le faire.
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()