在多处理中使Singleton类 [英] Make Singleton class in Multiprocessing

查看:64
本文介绍了在多处理中使Singleton类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用元类创建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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆