python多进程问题的思考

    def fun(produceQueue, key, consumerQueue):
        if not produceQueue.empty():
            args = produceQueue.get()
        else:
            raise Exception("produce queue is empty!")
        originX, originY, target, num = args[0], args[1], args[2], args[3]
        factor_dict = self.model_predict(originX, originY, target, key=key)
        consumerQueue.put({key: factor_dict})
        consumerQueue.join_thread()

if __name__ == '__main__':
    produceQueue = Queue(3)
    consumerQueue = Queue(3)
    pList = []
    for key in range(3):
        p = Process(target=fun, args=(produceQueue, key, consumerQueue))
        pList.append(p)
        p.start()
    for p in pList:
        p.join() #阻塞主线程

以上是我用python的多线程multiprocessing模块做的测试,主要是创建了三个子线程,用来并行执行业务逻辑以提高效率

我的开发环境是win10 8核 所以没有开启进程池

 

当用pycharm跑的时候抛出了错误:

TypeError: cannot serialize '_io.BufferedReader' object
Can't pickle attribute *** from ***

通过查阅StackOverflow网上的解释和百度,说的是对象没有序列化,因为进程间是不能通信的,而传的参数可能是主进程的全局变量从而导致报错

但是我的程序是根据队列的形式来进行进程间通信的,按理说不可能存在临界资源异常的问题,于是又往下找原因,一步一步debug,后来在Anaconda3\Lib\multiprocessing\popen_spawn_win32.py代码中发现了端倪

reduction.dump(process_obj, to_child)

这一步语句是指将对象序列化到子进程中,就是这句报错导致程序一直不成功,后来查看源代码,说的是该方法要调用创建进程的fork方法,而windows系统上不支持这样的方法,从而导致报错 晕~~~

后来将整个项目用docker部署好后,上述代码完全可以执行,没有报任何的错,但是却出现了返回的字典的key列表的维数是二维甚至一维的情况,由于是并发执行,说明有进程没有参与工作

参考这篇博客:

https://www.cnblogs.com/bigtreei/p/7988804.html

找到了点启发

原来是qList位主进程中的变量,在做循环join的时候总有主进程快于子进程的时候,而此时没来的及阻塞主进程,程序就退出了,从而消费者队列上面的数据就少了,所以将代码改成

for key in range(3):
        p = Process(target=fun, args=(produceQueue, key, consumerQueue))
        pList.append(p)
        p.start()
        p.join() #阻塞主线程

就完全没有问题了,不过牺牲了性能效率,因为每次开启子进程就要去阻塞主进程,仿佛给人的感觉是串行,但是得到的结果是正确的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值