在多处理中使Singleton类 [英] Make Singleton class in Multiprocessing
问题描述
我使用元类创建Singleton类,它在多线程中运行良好,并且仅创建MySingleton类的一个实例,但是在多处理中,它总是创建新的实例
I create Singleton class using Metaclass, it working good in multithreadeds and create only one instance of MySingleton class but in multiprocessing, it creates always new instance
import multiprocessing
class SingletonType(type):
# meta class for making a class singleton
def __call__(cls, *args, **kwargs):
try:
return cls.__instance
except AttributeError:
cls.__instance = super(SingletonType, cls).__call__(*args, **kwargs)
return cls.__instance
class MySingleton(object):
# singleton class
__metaclass__ = SingletonType
def __init__(*args,**kwargs):
print "init called"
def task():
# create singleton class instance
a = MySingleton()
# create two process
pro_1 = multiprocessing.Process(target=task)
pro_2 = multiprocessing.Process(target=task)
# start process
pro_1.start()
pro_2.start()
我的输出:
init called
init called
我需要MySingleton类 init 方法仅被调用一次
I need MySingleton class init method get called only once
推荐答案
您的每个子进程都运行自己的Python解释器实例,因此一个进程中的SingletonType
与其他进程中的状态不共享.这意味着仅存在于您的进程中的一个真正的单例几乎没有用,因为您将无法在其他进程中使用它:尽管您可以
Each of your child processes runs its own instance of the Python interpreter, hence the SingletonType
in one process doesn't share its state with those in another process. This means that a true singleton that only exists in one of your processes will be of little use, because you won't be able to use it in the other processes: while you can manually share data between processes, that is limited to only basic data types (for example dicts and lists).
无需依赖单例,只需在进程之间共享基础数据:
Instead of relying on singletons, simply share the underlying data between the processes:
#!/usr/bin/env python3
import multiprocessing
import os
def log(s):
print('{}: {}'.format(os.getpid(), s))
class PseudoSingleton(object):
def __init__(*args,**kwargs):
if not shared_state:
log('Initializating shared state')
with shared_state_lock:
shared_state['x'] = 1
shared_state['y'] = 2
log('Shared state initialized')
else:
log('Shared state was already initalized: {}'.format(shared_state))
def task():
a = PseudoSingleton()
if __name__ == '__main__':
# We need the __main__ guard so that this part is only executed in
# the parent
log('Communication setup')
shared_state = multiprocessing.Manager().dict()
shared_state_lock = multiprocessing.Lock()
# create two process
log('Start child processes')
pro_1 = multiprocessing.Process(target=task)
pro_2 = multiprocessing.Process(target=task)
pro_1.start()
pro_2.start()
# Wait until processes have finished
# See https://stackoverflow.com/a/25456494/857390
log('Wait for children')
pro_1.join()
pro_2.join()
log('Done')
此打印
16194: Communication setup
16194: Start child processes
16194: Wait for children
16200: Initializating shared state
16200: Shared state initialized
16201: Shared state was already initalized: {'x': 1, 'y': 2}
16194: Done
但是,根据您的问题所在,可能会使用其他进程间通信机制提供更好的解决方案.例如, Queue
类通常非常有用
However, depending on your problem setting there might be better solutions using other mechanisms of inter-process communication. For example, the Queue
class is often very useful.
这篇关于在多处理中使Singleton类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!