Süreçlerde sınıf üyelerini nasıl güncelleyebilirim? [çiftleme]

Dec 26 2020

Başka sorular aradım ve bu kabul edilmemiş soru , bir şekilde bu konuyu ele aldığını ve gerçekten yardımcı olmadığını bulabildiğim tek soru . Ayrıca, iş parçacıklarıyla değil süreçlerle çalışmak için buna ihtiyacım var.

Bu yüzden, baştan sona sorunumu göstermek için örnek bir program yazdım, yapıştırabilmeniz gerekir ve çalışacaktır:

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

Bu bana ya elmanın aynı anda iki renk olduğu garip bir varsayımda olduğunu ya da new_process 'elmasının koçta başka bir konumda olduğunu ve ana süreçte elmadan ayrıldığını söylüyor.

Öyleyse soru şu: İşlemdeki elmanın işaretçisinin aynı elmayı göstermesinin bir yolu var mı, yoksa tüm süreçlerde elmanın tüm örneklerini aynı tutmanın pitonik yolu nedir? Ya birçok işlemde ve hatta daha fazla işlemde aynı elmaya sahipsem, alanlarının hep aynı olduğundan nasıl emin olabilirim?

Yanıtlar

2 martineau Dec 27 2020 at 21:28

ProxyTarafından kullanılan multiprocessing.BaseManager(belgelenmemiş) multiprocessing.managers.NamespaceProxy, temel sınıftan farklı olarak tüm yöntemlerini ve özniteliklerini ortaya çıkaran bir sınıfın özelleştirilmiş bir sürümünü türetebilirsiniz . Bu, @ shtse8'in bağlantılı yinelenen soruya verdiği yanıta benzer, ancak nasıl yapılacağını açıklığa kavuşturmak için gönderiyorum.

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