当页面附加到页面列表时,我正在尝试传递工作,但我的代码输出返回NotImplementedError。以下是我正在尝试做的代码:
代码:
from multiprocessing import Pool, current_process
import time
import random
import copy_reg
import types
import threading
class PageControler(object):
def __init__(self):
self.nProcess = 3
self.pages = [1,2,3,4,5,6,7,8,9,10]
self.manageWork()
def manageWork(self):
self.pool = Pool(processes=self.nProcess)
time.sleep(2)
work_queue = threading.Thread(target=self.modifyQueue)
work_queue.start()
#pool.close()
#pool.join()
def deliverWork(self):
if self.pages != []:
pag = self.pages.pop()
self.pool.apply_async(self.myFun)
def modifyQueue(self):
t = time.time()
while (time.time()-t) < 10:
time.sleep(1)
self.pages.append(99)
print self.pages
self.deliverWork()
def myFun(self):
time.sleep(2)
if __name__ == '__main__':
def _pickle_method(m):
if m.im_self is None:
return getattr, (m.im_class, m.im_func.func_name)
else:
return getattr, (m.im_self, m.im_func.func_name)
copy_reg.pickle(types.MethodType, _pickle_method)
PageControler()
输出:
NotImplementedError: pool objects cannot be passed between processes or pickled
是否可以在进程之间传递池对象?
修改
我正在使用Python 2.6
答案 0 :(得分:25)
为了挑选您尝试传递给Pool
的实例方法,Python需要挑选整个PageControler
对象,包括其实例变量。其中一个实例变量是Pool
对象本身,而Pool
个对象无法被腌制,因此会出错。您可以通过在对象上实现__getstate__
来解决此问题,并使用它在酸洗之前从实例中删除pool
对象:
class PageControler(object):
def __init__(self):
self.nProcess = 3
self.pages = [1,2,3,4,5,6,7,8,9,10]
self.manageWork()
def manageWork(self):
self.pool = Pool(processes=self.nProcess)
time.sleep(2)
work_queue = threading.Thread(target=self.modifyQueue)
work_queue.start()
#pool.close()
#pool.join()
def deliverWork(self):
if self.pages != []:
pag = self.pages.pop()
self.pool.apply_async(self.myFun)
def modifyQueue(self):
t = time.time()
while (time.time()-t) < 10:
time.sleep(1)
self.pages.append(99)
print self.pages
self.deliverWork()
def myFun(self):
time.sleep(2)
def __getstate__(self):
self_dict = self.__dict__.copy()
del self_dict['pool']
return self_dict
def __setstate__(self, state):
self.__dict__.update(state)
__getstate__
总是在腌制对象之前调用,并允许您准确指定对象的状态应该实际被腌制。然后在取消修改时,__setstate__(state)
将被调用(如果它是在我们的情况下),或者如果不是,则dict
返回的__getstate__
将被用作对于未打开的实例,__dict__
。在上面的示例中,我们明确地将__dict__
设置为我们在dict
中返回的__getstate__
,但我们可能没有实现__setstate__
并获得相同的效果
答案 1 :(得分:1)
如果必须将整个对象传递给流程,Dano的答案是一个很好的方法。在您的情况下,您传递给池的函数不需要对类实例的引用。所以另一种方法是使用@staticmethod
装饰器使函数成为静态方法。如果函数确实需要引用一个或两个类成员变量,那么它们可以作为只读变量的参数传入,如果还需要写入则在回调中更新(当然,如果你想要,你需要这样做)在任何情况下都更新本地类实例。)
例如:
Class A(object):
def __init__(self):
self._pool = multiprocessing.Pool(1)
self.member_variable = 1
@staticmethod
def MyFunc(variable):
variable += 1
return variable
def Callback(self, return_val):
self.member_variable = return_val
def CallFuncAsync(self):
pool.apply_async(self.MyFunc, (self.member_variable,), callback=self.Callback)