Python 多处理,pool.ready做什么?

Python 多处理,pool.ready做什么?,python,multiprocessing,pool,Python,Multiprocessing,Pool,假设我有一个池,在一个类中有几个进程,我用它来做一些处理,如下所示: class MyClass: def __init_(self): self.pool = Pool(processes = NUM_PROCESSES) self.pop = [] self.finished = [] def gen_pop(self): self.pop = [ self.pool.apply_async(Item.tes

假设我有一个池,在一个类中有几个进程,我用它来做一些处理,如下所示:

class MyClass:

    def __init_(self):
        self.pool = Pool(processes = NUM_PROCESSES)
        self.pop = []
        self.finished = []

    def gen_pop(self):
        self.pop = [ self.pool.apply_async(Item.test, (Item(),)) for _ in range(NUM_PROCESSES) ]
        while (not self.check()):
            continue
        # Do some other stuff

    def check(self):
        self.finished = filter(lambda t: self.pop[t].ready(), range(NUM_PROCESSES))
        new_pop = []
        for f in self.finished:
            new_pop.append(self.pop[f].get(timeout = 1))
            self.pop[f] = None
            # Do some other stuff
当我运行这段代码时,我会得到一个
cPickle.PicklingError
,它表明
不能被pickle。这告诉我一个
apply\u async
函数尚未返回,因此我试图将一个正在运行的函数附加到另一个列表中。但这不应该发生,因为所有正在运行的调用都应该使用
ready()
函数过滤掉

与此相关的一点是,
类的实际性质并不重要,但重要的是在我的
项的顶部。test
函数中有一个print语句,该语句应该用于调试目的。然而,这并没有发生。这告诉我函数已经启动,但实际上还没有开始执行


因此,看来
ready()
实际上并没有告诉我调用是否已完成执行。
ready()
具体做什么?我应该如何编辑我的代码,以便过滤掉仍在运行的进程?

多处理在内部使用
pickle
模块在进程之间传递数据, 因此,您的数据必须是可拾取的。请参见,对象方法不在该列表中。
要快速解决此问题,只需在方法周围使用包装函数:

def wrap_item_test(item):
    item.test()

class MyClass:
    def gen_pop(self):
        self.pop = [ self.pool.apply_async(wrap_item_test, (Item(),)) for _ in range(NUM_PROCESSES) ]
        while (not self.check()):
            continue

为了回答您提出的问题,
.ready()
确实在告诉您
.get()
是否可以阻止:如果
.ready()
返回
True
.get()
不会阻止,但是如果
.ready()
返回
False
.get()
可以阻止(也可能不是:很可能异步调用将在您开始调用
.get()
之前完成)

因此,例如,
.get()
中的
timeout=1
没有任何作用:因为如果
.ready()
返回
True
,则只调用
.get()
,您已经知道
.get()
不会阻塞

但是
.get()
不阻塞并不意味着异步调用成功,甚至工作进程甚至开始处理异步调用:正如文档所说

如果远程调用引发异常,则将通过
get()
重新调用该异常

也就是说,例如,如果根本无法执行异步调用,
.ready()
将返回
True
.get()
将(重新)引发阻止尝试工作的异常

这似乎就是您的情况,尽管我们不得不猜测,因为您没有发布可运行代码,也没有包含回溯

请注意,如果您真正想知道的是,在从
.ready()
返回
True
后,异步调用是否正常完成,那么
.successful()
就是要调用的方法


很明显,无论
Item.test
可能是什么,由于pickle限制,根本不可能将其作为可调用的
.apply\u async()
传递。这就解释了为什么
Item.test
从不打印任何内容(实际上从未调用过!),为什么
.ready()
返回
True
(the
.apply\u async()
调用失败),以及为什么
.get()
引发异常(因为
.apply\u async()
在尝试pickle其一个参数时遇到异常-可能是
项。test
).

你为什么认为
cPickle.PicklingError
就是这个意思?@zwol我真的不这么认为。相反,我认为这个错误是实际问题的一个症状,这在我的问题中有详细说明。我想说的是,我认为你对实际问题的诊断是错误的。那么,我能把
包装项目测试
放在包含
项的e模块
?或者我还需要知道什么?