프로세스에서 클래스 멤버를 업데이트하려면 어떻게해야합니까? [복제]

Dec 26 2020

나는 다른 질문을 찾아 봤는데, 이 대답이 받아 들여지지 않은이 질문 은 어떻게 든이 문제를 다루고 있고 실제로 도움이되지 않는 유일한 질문 입니다. 또한 스레드가 아닌 프로세스로 작업하려면 이것이 필요합니다.

그래서 처음부터 내 문제를 보여주기 위해 샘플 프로그램을 작성했습니다. 붙여 넣을 수 있고 실행됩니다.

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

이것은 사과가 동시에 두 가지 색상 인 이상한 가정에 있거나 new_process '사과가 램의 다른 위치에 있고 주요 프로세스에서 사과와 분리되어 있다는 것을 알려줍니다.

그래서 질문은 : 프로세스에서 사과의 포인터가 동일한 사과를 가리 키도록하는 방법이 있습니까, 아니면 모든 프로세스에서 사과의 모든 인스턴스를 동일하게 유지하는 비 단식적인 방법은 무엇입니까? 여러 프로세스에 동일한 사과가 있고 사과가없는 더 많은 프로세스에있는 경우 어떻게 항상 동일한 면적을 확보 할 수 있습니까?

답변

2 martineau Dec 27 2020 at 21:28

기본 클래스와 달리 모든 메서드와 특성을 노출 하는 (문서화되지 않은)에서 Proxy사용되는 클래스 의 특수 버전을 파생 할 수 있습니다 . 이것은 연결된 중복 질문에 대한 @ shtse8의 답변과 비슷하지만 어떻게해야하는지 명확히하기 위해 게시하고 있습니다.multiprocessing.BaseManagermultiprocessing.managers.NamespaceProxy

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()