multiprocess模块使用进程池调用apply_async()提交的函数及回调函数不执行问题

来源:互联网 发布:美工在线培训 编辑:程序博客网 时间:2024/06/05 13:25


使用multiprocesss模块遇到各种各样的问题,这次遇到的问题是调用进程池对象的 apply_async() 方法,往进程池传递一个实例方法(该实例方法里有一段代码是往同步队列里放入数据),然后发现往进程池扔的任务(即实例方法)不会被执行,回调方法也不执行。心塞~


以下是出现问题的代码

import ctypesimport datetimeimport randomimport timefrom multiprocessing import Queuefrom multiprocessing.pool import Poolfrom multiprocessing import Valueclass entry(object):    def __init__(self, s: str, queue: Queue):        self.s = s        self.queue = queue        # self.counter = c_uint    def cutString(self):        index = random.randint(0, len(self.s) - 4)        time.sleep(1)        i = random.randint(0, 2)        print("randint(0, 2) = {}".format(i))        return self.s[index:index + 2]    def exec(self):        # self.counter.value += 1        substring = self.cutString()        # 往队列里放数据        self.queue.put(substring)        return substring    # 回调函数    def display(self, s):        global index        index += 1        print("callback ----> {} :\t{}".format(index-1, s))if __name__ == '__main__':    param = "0123456789abcdefghijklmnopqrstuvwxyz"    val = Value(ctypes.c_uint32, 1)    index = 1    queue = Queue()    # 测试9个进程的进程池执行 doMatch() 函数30次需要的时间    pool1 = Pool(9)    start = datetime.datetime.now()    for i in range(30):        e = entry(param, queue)        pool1.apply_async(e.exec, callback=e.display)    pool1.close()    pool1.join()    finish = datetime.datetime.now()    tmp = []    while not queue.empty():        tmp.append(queue.get())    print("9个进程的进程池执行结果:\n{}".format(tmp))    print("9个进程的进程池执行花费的时间为:\t{}".format(finish - start))    # 测试3组3个进程的进程池执行 doMatch() 函数30次需要的时间    pool2 = Pool(3)    pool3 = Pool(3)    pool4 = Pool(3)    pools = [pool2, pool3, pool4]    index = 1    start = datetime.datetime.now()    for j in range(len(pools)):        for i in range(10):            e = entry(param, queue)            pools[j].apply_async(e.exec, callback=e.display)        pools[j].close()    for j in range(len(pools)):        pools[j].join()    finish = datetime.datetime.now()    print("3组3个进程的进程池执行花费的时间为:\t{}".format(finish - start))    tmp = []    while not queue.empty():        tmp.append(queue.get())    print("3组3个进程的进程池执行结果:\n{}".format(tmp))

运行结果


这里写图片描述


把以上出问题的代码进行如下修改:


这里写图片描述

修改后再运行的结果如下


这里写图片描述


另外,如果传递给apply_async()的函数如果有参数,需要以元组的形式传递 并在最后一个参数后面加上 , 号,如果没有加, 号,提交到进程池的任务也是不会执行的

以以下代码为例:

def shareMemory(c_uint):    # print("c_uint = {}".format(c_uint.value))    print("c_uint = {}".format(c_uint))    # c_uint = 1 + c_uint.value    c_uint = 1 + c_uint    time.sleep(1)    # res = "c_uint = {}".format(c_uint.value)    res = "c_uint = {}".format(c_uint)    return resdef display(s: str):    print("callback -------> {}".format(s))if __name__ == '__main__':    param = "0123456789abcdefghijklmnopqrstuvwxyz"    # val = Value(ctypes.c_uint32, 1)    val = 1    # 测试9个进程的进程池执行 shareMemory(c_uint) 函数30次需要的时间    pool1 = Pool(9)    start = datetime.datetime.now()    for i in range(30):        pool1.apply_async(shareMemory, (val,), callback=display)    pool1.close()    pool1.join()    finish = datetime.datetime.now()    print("9个进程的进程池执行花费的时间为:\t{}".format(finish - start))

测试的运行结果如下


这里写图片描述

修改传递给 apply_async() 函数所需要的参数,具体如下所示:


这里写图片描述


总结:

原本想用apply_async()里传递1个函数,把函数执行过程中产生的中间结果放到队列里供其它进程消费的,结果放到进程池里的任务压根就不会执行,我觉得不执行的原因可能为同步队列有阻塞行为,所以直接导致了提交的任务被拒绝执行

如果提交到进程池的任务函数有参数,需要在调用apply_async()方法时在第二个参数指明传递给提交任务函数的参数,第二个参数类型为元组。如果未在元组的最后一个元素加上”,”也会导致提交到进程池的任务不执行;我觉得提交给进程池的任务函数不执行的主要原因可能是函数缺少参数导致了函数执行时出现异常直接退出

虽然重现了往apply_async()传递一个带同步操作的函数不执行的现象,但还是没有找到其根本原因;本人菜鸟一枚,如哪位大神看到此博文有不妥之处还望斧正。


至于往apply_async()传递一个同步队列操作的函数为什么不会被执行的问题,博主现在也不清楚,希望有大神可以指教

阅读全文
0 0
原创粉丝点击