回调函数在使用多进程时未被调用

6

我花了一整天的时间调试以下代码,它与多进程有关。请看一下。

import numpy as np
import multiprocessing as mp


def printHello(x):
    print "ENTERING: printHello"
    time.sleep(2)
    print "QUITTING: printHello"
    return 'hello '+x

def log_result(result):
    print "ENTERING: log_result"
    time.sleep(2)
    print "QUITTING: log_result"

def main_multi():
    pool = mp.Pool()
    for i  in range(3):
        pool.apply_async(printHello, args=(i, ), callback=log_result)
    pool.close()
    pool.join()

if __name__=='__main__':
    print "ENTERING __main__"
    main_multi()
    print "QUITTING __main__"

我原本想在输出的行中看到“QUITTING:printHello”、“ENTERING:log_result”和“QUITTING:printHello”。让我感到奇怪的是,当主程序停止时(没有任何“hello”的打印输出),printHello尚未完成;似乎“pool.join”语句被忽略了。也许上面的“callback”或“apply_async”不像我预期的那样工作。有什么思路吗?
我的控制台输出为:
ENTERING __main__
ENTERING: printHello
ENTERING: printHello
ENTERING: printHello
QUITTING __main__ 

[编辑] 有趣的是,如果我删除'time.sleep(2)'部分,我会得到

ENTERING __main__
ENTERING: printHello
QUITTING: printHello
ENTERING: printHello
QUITTING: printHello
ENTERING: printHello
QUITTING: printHello
QUITTING __main__

但这仍然不能解决所有问题。因为在'helloPrint'中的'hello'没有被打印出来,尽管我在apply_async之后有一个pool.join。
[编辑2]我刚刚添加了'import time'。症状仍然存在:pool.join应该阻塞直到进程终止,但在这里并非如此。

出于好奇,删除time.sleep(2)语句会有什么影响吗? - user1245262
谢谢你的提示。请看我上面的编辑。 - zell
1个回答

6
您还没有导入time模块,因此调用time.sleep会导致工作进程出错。这就是为什么您无法收到"QUITTING"消息,回调函数也不会被调用。
如果您解决了这个问题,当您尝试生成返回值时,仍然会在工作进程中遇到错误。您将传递的整数x添加到字符串"hello"中,这是不明确的。您需要将整数转换为字符串,以使字符串连接正常工作。

哇!太棒了!你知道是否有一种方法可以在运行时获取这样的错误信息吗? - zell
1
谢谢解释。现在,我想知道如何查看工作进程生成的错误? - user1245262
2
如果您保留池的apply_async方法返回的AsyncResult值,您将能够通过调用其get方法来获取异常(该方法引发在工作进程中捕获的异常)。Python 3的concurrent.futures模块做得更好一些,因为您可以为异步调用设置回调,并且在正常和错误情况下都使用Future对象本身调用它们。 - Blckknght
最近我遇到了类似的问题(不是时间,而是日期),我发现定义error_callbackcallback有所帮助,这样每个进程的错误都能被处理,而不是默默失败。 - Rob Streeting

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接