在python多处理工作池中使用initialize

时间:2012-03-30 13:55:01

标签: python multiprocessing

我正在研究工人的多处理。工具,试图初始化一些状态的工人。池可以采用可调用的初始化,但不会传递对初始化worker的引用。我见过的几个例子利用它调用全局变量,这看起来真的很讨厌。

有没有什么好方法可以使用multiprocessing.Pool来初始化worker状态?

编辑:一个例子:

我有工作人员,每个人都做一些相对昂贵的初始化(绑定到套接字),我不想每次都这样做。我可以手动初始化我的套接字,然后在分配工作时传递它们,但是跨进程共享文件描述符是复杂的,如果不是不可能的话。因此,每次我想处理请求时,我都必须进行初始化和绑定。

1 个答案:

答案 0 :(得分:2)

从技术上讲,正确的做法是将初始化函数的结果作为参数传递给工作者执行的每个函数。

同样正确的是,在这种情况下,拥有全局变量是好的和安全的,因为通过构造它们会导致私有对象生活在不同进程的不同域中。

我的一般建议是使用合理的reentrant编程风格构建函数,并在利用multiprocessing功能时允许全局变量。

保留您的示例,以下send函数需要一些上下文(在本例中为 socket ):

def send(socket, data):
    pass # ... your code here
    return dust

为方便起见,工作人员执行的初始化代码和基本代码将依赖于全局变量。

socket = None
def init(address, port):
    global socket
    socket = magic(address, port)

def job(data):
    global socket
    assert socket is not None
    return send(socket, data)

pool = multithreading.Pool(N, init, [address, port])
pool.map(job, ['foo', 'bar', 'baz'])

通过以这种方式对其进行编码,在没有多处理的情况下测试它变得简单而自然。您可以将您的全球状态视为一个非常安全的上下文包。

作为额外的便利点,请注意multiprocessing并不擅长发送复杂数据(例如回调)。最好的方法是发送简单的数据(字符串,列表,字典,collections.namedtuple ...),并在工作方重建复杂的数据结构(使用初始化函数)。