为什么不能将process
中的Pool
放入Queue
中?
在这里,我的代码在使用Pool
时有效,并且可以获得Test
实例属性。
from multiprocessing import Pool
from multiprocessing import Queue
class Test(object):
def __init__(self, num):
self.num = num
if __name__ == '__main__':
p = Pool()
procs = []
for i in range(5):
proc = p.apply_async(Test, args=(i,))
procs.append(proc)
p.close()
for each in procs:
test = each.get(10)
print(test.num)
p.join()
当我尝试使用Queue
而不是python list
来存储进程时,这将不起作用。
我的代码:
from multiprocessing import Pool
from multiprocessing import Queue
class Test(object):
def __init__(self, num):
self.num = num
if __name__ == '__main__':
p = Pool()
q = Queue()
for i in range(5):
proc = p.apply_async(Test, args=(i,))
q.put(proc)
p.close()
while not q.empty():
q.get()
p.join()
错误消息:
Traceback (most recent call last):
File "C:\Users\laich\AppData\Local\Programs\Python\Python36-
32\lib\multiprocessing\queues.py", line 234, in _feed
obj = _ForkingPickler.dumps(obj)
File "C:\Users\laich\AppData\Local\Programs\Python\Python36-
32\lib\multiprocessing\reduction.py", line 51, in dumps
cls(buf, protocol).dump(obj)
TypeError: can't pickle _thread.lock objects
我去看看多处理文档:
class multiprocessing.Queue([maxsize])
返回使用管道和一些锁/信号量实现的进程共享队列。当进程首先将项目放入队列时,将启动一个供料器线程,该线程将对象从缓冲区转移到管道中。标准库的队列模块中常见的
queue.Empty
和queue.Full
异常引发了超时。除
queue.Queue
和task_done()
之外,Queue实现了join()
的所有方法。
这里说“放一个东西”,这个东西不能是任何东西(python对象)?以我为例,我尝试将process
中的Pool()
放入Queue
中。
答案 0 :(得分:0)
基于Queue
的代码至少存在两个问题。 Pool.apply_async
方法返回一个AsyncResult
对象,而不是进程。您可以对此对象调用get
,以获取相应过程的结果。考虑到这种差异,让我们看一下您的代码:
proc = p.apply_async(Test, args=(i,)) # Returns an AsyncResult object
q.put(proc) # won't work
根据您的情况,第二行将始终失败。您放入队列中的任何内容都必须是可挑剔的,因为multiprocess.Queue
使用序列化。这没有很好的文档说明,Python的问题跟踪器中有一个open issue用于更新文档。问题是AsyncResult
不可腌制。您可以尝试一下:
import pickle
import multiprocessing as mp
with mp.Pool() as p:
result = p.apply_async(lambda x: x, (1,))
pickle.dumps(result) # Error
AsyncResult
内部包含一些锁定对象,并且它们无法序列化。让我们转到下一个问题:
while not q.empty():
q.get()
如果我没记错的话,在上面的代码中,您想调用AsyncResult.get
而不是Queue.get
。在这种情况下,您必须首先从队列中获取对象,然后在对象上调用相应的方法。但是,由于AsyncResult
不可序列化,因此代码中不是这种情况。
答案 1 :(得分:0)
就像@Mehdi Sadeghi explained一样,AsyncResult
个对象不能被腌制,multiprocessing.Queue
被要求。但是,这里不需要一个队列,因为队列没有在进程之间共享。这意味着您只能使用常规的Queue
。
from multiprocessing import Pool
#from multiprocessing import Queue
from queue import Queue
class Test(object):
def __init__(self, num):
self.num = num
print('Test({!r}) created'.format(num))
if __name__ == '__main__':
p = Pool()
q = Queue()
for i in range(5):
proc = p.apply_async(Test, args=(i,))
q.put(proc)
p.close()
while not q.empty():
q.get()
p.join()
print('done')
输出:
Test(0)
Test(1)
Test(2)
Test(3)
Test(4)
done