Python中多处理模块的池和队列问题

时间:2017-04-23 15:20:25

标签: python python-multiprocessing

我是Python的多处理新手,我在下面写了一个小脚本:

import multiprocessing
import os

def task(queue):
    print(100)

def run(pool):
    queue = multiprocessing.Queue()
    for i in range(os.cpu_count()):
        pool.apply_async(task, args=(queue, ))

if __name__ == '__main__':
    multiprocessing.freeze_support()
    pool = multiprocessing.Pool()
    run(pool)
    pool.close()
    pool.join()

我想知道为什么没有执行task()方法,并且在运行此脚本后没有输出。有谁可以帮助我?

1 个答案:

答案 0 :(得分:2)

它正在运行,但它在主线程外部出现错误而死亡,因此您没有看到错误。因此,.get()异步调用的结果始终是好的,即使您不关心结果:.get()会引发原本不可见的错误。

例如,像这样更改循环:

tasks = []
for i in range(os.cpu_count()):
    tasks.append(pool.apply_async(task, args=(queue,)))
for t in tasks:
    t.get()

然后新的t.get()会爆炸,结束于:

RuntimeError: Queue objects should only be shared between processes through inheritance

简而言之,不支持将Queue个对象传递给Pool方法。

可以将它们传递给multiprocessing.Process()Pool初始化函数。例如,这是一种做后者的方法:

import multiprocessing
import os

def pool_init(q):
    global queue # make queue global in workers
    queue = q

def task():
    # can use `queue` here if you like
    print(100)

def run(pool):
    tasks = []
    for i in range(os.cpu_count()):
        tasks.append(pool.apply_async(task))
    for t in tasks:
        t.get()

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    pool = multiprocessing.Pool(initializer=pool_init, initargs=(queue,))
    run(pool)
    pool.close()
    pool.join()

在Linux-y系统上,您可以 - 建议使用原始错误消息 - 改为使用进程继承(但这在Windows上是不可能的)。