Python разделяет одноэлементный объект между дочерними процессами - PullRequest
0 голосов
/ 30 августа 2018

Я знаю, что процессы не имеют общего контекста в Python. Но как насчет одиночных объектов? Мне удалось получить дочерний процесс с тем же внутренним объектом, что и родительский процесс, но я не могу понять, как. Что-то не так с кодом ниже?

Это может быть продолжение до этого вопроса стекопотока .

Это код, который у меня есть:

Singleton.py:


import os

class MetaSingleton(type):
     _instances = {}

def __call__(cls, *args, **kwargs):
    if cls not in cls._instances:
        cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
    return cls._instances[cls]

class Singleton:
   __metaclass__ = MetaSingleton

   def __init__(self):
       self.key="KEY TEST"
       print "inside init"

   def getKey(self):
       return self.key

  def setKey(self,key1):
       self.key = key1

  process_singleton.py:


  import os
  from Singleton import Singleton

  def callChildProc():
       singleton = Singleton()
       print ("singleton key: %s"%singleton.getKey())

  def taskRun():
       singleton = Singleton()
       singleton.setKey("TEST2")
       for i in range(1,10):
           print ("In parent process, singleton key: %s" %singleton.getKey())
        try:
           pid = os.fork()
        except OSError,e:
           print("Could not create a child process: %s"%e)

        if pid == 0:
            print("In the child process that has the PID %d"%(os.getpid()))
           callChildProc()
           exit()

       print("Back to the parent process")

 taskRun()

1 Ответ

0 голосов
/ 30 августа 2018

В системах разветвления дочерние процессы имеют копию при записи записи родительского пространства памяти. Процессы используют виртуальную память, и сразу после разветвления оба виртуальных пространства процесса указывают на одну и ту же физическую память. При записи физическая страница копируется, а виртуальная память перераспределяется, поэтому бит памяти больше не используется совместно. Эта отложенная копия обычно быстрее, чем клонирование пространства памяти на развилке.

В результате ни один из родителей или ребенок не видит изменений в других сторонах. Поскольку вы настраиваете синглтон перед разветвлением, родитель и потомок видят одно и то же значение.

Вот краткий пример, где я использую time.sleep, чтобы контролировать, когда родитель и ребенок вносят свои личные изменения:

import multiprocessing as mp
import time

def proc():
    global foo
    time.sleep(1)
    print('child foo should be 1, the value before the fork:', foo)
    foo = 3 # child private copy


foo = 1 # the value both see at fork
p = mp.Process(target=proc)
p.start()
foo = 2 # parent private copy
time.sleep(2)
print('parent foo should be 2, not the 3 set by child:', foo)

При запуске:

child foo should be 1, the value before the fork: 1
parent foo should be 2, not the 3 set by child: 2
...