为什么我的子进程由pool.apply_async()生成的总是作为MainProcess运行?

时间:2016-10-09 07:49:51

标签: python

我的环境是Python2.7。我非常模糊,我运行了apply_async(test_func),我让test_func打印当前的process_name。如:

q = Queue(maxsize=20) #multiprocessing.Queue

def test_func(queue):
    print 'Process'
    print multiprocessing.current_process()

if __name__ == '__main__':
    pool = Pool(processes=3)
    for i in xrange(3):
        pool.apply_async(test_func(q,))
    while True:
        time.sleep(1)
        if q.empty():
            break
        print 'Main Process Monitoring'
        print multiprocessing.current_process()

代码没有语法错误,终端始终打印<MainProcess>

如果我更改pool.apply_async(test_func,(q,))(add a comma),则无法进入test_func,就像完成循环一样,只打印'Main Process Monitoring' <MainProcess> ..

所以我无法理解为什么apply_async()无法正常工作,当它工作时,它会以MainProcess运行,而我已尝试过pool.close(),pool.join()。 。 如果有人可以提供帮助。非常感谢!

2 个答案:

答案 0 :(得分:1)

首先,您的test_func函数没有return语句,因此返回None

def test_func(queue):
    print 'Process'
    print multiprocessing.current_process()

将其插入交互式Python:

>>> import multiprocessing
>>> x = test_func(None)
Process
<_MainProcess(MainProcess, started)>
>>> print x
None

这意味着:

    pool.apply_async(test_func(q,))

使用参数test_func调用(q,),返回None;然后你将None传递给pool.apply_async

The multiprocessing documentationapply_async描述为调用其第一个参数a la apply,但是异步,即不等待其结果。让我们以交互方式尝试apply(None),看看它是做什么的:

>>> apply(none)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

所以我们可能期望apply_async引发一个TypeError--事实上, 它的作用是什么,但错误是推迟到我们试图得到结果之前:

>>> pool = multiprocessing.Pool(processes=3)
>>> pool.apply_async(None)
<multiprocessing.pool.ApplyResult object at 0x801b27510>

让我们抓住这个ApplyResult对象,以便我们可以使用和检查它(特殊名称_保存交互期间返回的最新值):

>>> x = _

现在我们可以看到异步应用是否对我们有效:

>>> x.ready()
True

确实如此! (如果没有,我们可以调用x.wait()等待它,但由于现在已经准备就绪,让我们按下。)结果是常规值还是异常?

>>> x.successful()
False

啊,结果是一个例外。我们得到例外:

>>> x.get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/multiprocessing/pool.py", line 567, in get
    raise self._value
TypeError: 'NoneType' object is not callable

我们得到了答案:将None传递给apply_async旋转执行函数None(毕竟这不是函数),并且一旦我们收集了最终结果结果,结果是我们期望的例外。

  

如果我更改pool.apply_async(test_func,(q,))(添加逗号),则无法进入test_func ...

让我们在交互式解释器中尝试类似的东西。我没有q,但由于test_func实际上并没有使用它的参数,所以我们可以通过无:

>>> x = pool.apply_async(test_func, (None,))
>>> Process
<Process(PoolWorker-2, started daemon)>

这个输出有点乱,但看起来确实有效。让我们看看x是否有结果,以及它是否成功,以及结果如何:

x.ready()
True
>>> x.successful()
True
>>> x.get()
>>>

(第一个>>>提示似乎丢失了,但它实际上只是被test_func中打印的内容打印出来了。有一个成功的价值,但由于它是无,解释器在这里没有打印任何东西 - 我们必须完成print x.get()才能看到它。

换句话说,如果你打算使用apply_async,你必须(1)在某处保存旋转的“待定结果”,然后(2)使用.get()实际检索结果。您还需要从函数中返回一些内容。

同时这个循环:

while True:
    time.sleep(1)
    if q.empty():
        break
    print 'Main Process Monitoring'
    print multiprocessing.current_process()

永远不会一直运行,因为你的队列对象q 在你测试它时是是空的,所以你立即break了。

答案 1 :(得分:0)

偶尔,我知道我应该使用fname = raw_input("Enter file name: ") fh = open(fname) lst = list() for line in fh: word = line.split() for item in word: if item not in lst: lst.append(item) lst.sort() print(lst) ,这对我来说是个错误。

但奇怪的是,当我使用apply_async(test_func, (i,))时,它将无效。apply_async(test_func, (q,))是多处理.Queue()。如果我删除它或替换除Queue对象之外的任何其他对象,它会工作(正常打印子过程)

我不知道队列是否有某些错误或其他什么问题......

有人知道吗?非常感谢!