python 多进程共享对象(bug日记)

最近在改bug的时候 , 需要让父进程给子进程传一个复杂对象 , 

直接 

from multiprocessing import Process, Queue, Lock,Pipe,Manager

def func(arg):
    pass
if __name__=='__main__':
    Process(target=func,args=(arg,))

报错:不能被pickle ,不能序列化 . 于是考虑放到queue或者pipe中 , 又尝试用了dill (api和pickle一样) , 都报错:不能pickle.

谷歌到的内容 :

什么可以被 pickle

参见what is pickable

  • None,True,False,内建数字类型,字符串

  • picklable 对象组成的 tuple、list、set、dict

  • 在模块顶层中定义的函数、内建函数、类

  • 其 __dict__ 或 __getstate__() 是可 pickle 的类实例

  • 特别地,numpy ndarray

注意 lambda 匿名函数不可被 pickle,除非使用 dill 之类的包,见
详见 http://luly.lamost.org/blog/python_multiprocessing.html

尝试了Manager ,付一个manager共享对象的例子:


from multiprocessing import Process,Value,Lock
from multiprocessing.managers import BaseManager
class Employee(object):
    def __init__(self,name,salary):
        self.name=name
        self.salary=Value('i',salary)
    def increase(self):
        self.salary.value+=100
    def getPay(self):
        return self.name+':'+str(self.salary.value)
class MyManager(BaseManager):
    pass
def Manager2():
    m=MyManager()
    m.start()
    return m
MyManager.register('Employee',Employee)
 
def func1(em,lock):
    with lock:
        em.increase()
 
if __name__ == '__main__':
    manager=Manager2()
    em=manager.Employee('zhangsan',1000)
    lock=Lock()
    proces=[Process(target=func1,args=(em,lock))for i in xrange(10)]
    for p in proces:
        p.start()
    for p in proces:
        p.join()
    print em.getPay()

但是依然报错 ,无法在多进程中共享我的复杂对象 , 找到的答案是因为manager的通信接口过于简单,仅仅多支持了一些connection,event等类型 .

目前用线程替换了进程 , 线程的好处是子线程传参不需要序列化 , 且在多线程中可以拿到同一个单例对象 ,多个线程共享内存,而多进程不行 ; python多线程适用于io密集型操作 ,而多进程适用于cpu密集型操作,用于科学计算比较多 , 目前的应用场景多线程可以满足要求 .
目前仍未找到更好的办法.

猜你喜欢

转载自blog.csdn.net/yournevermore/article/details/88718745