python在子进程之间共享单例对象

时间:2018-08-30 16:06:08

标签: python process singleton fork

我知道进程在python中不会共享相同的上下文。但是单例对象呢?我能够使子进程与父进程共享相同的内部对象,但无法理解如何。下面的代码有什么问题吗?

这可能是对this stackoverflow question的后续行动。

这是我的代码:

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 :(得分:0)

在分叉系统上,子进程在父存储空间的写入视图中具有一个副本。进程使用虚拟内存,并且在派生之后,两个进程虚拟空间都指向同一物理RAM。在写入时,将复制物理页面,并重新映射虚拟内存,以便不再共享内存的位。通常,此延迟的副本比克隆分叉处的内存空间快。

结果是父母或孩子都看不到对方的变化。由于您在派生之前设置了单例,因此父级和子级都将看到相同的值。

这是一个简单的示例,其中我使用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