Python3多进程编程中进程池锁共享

python多进程编程使用进程池非常的方便管理进程,但是有时候子进程之间会抢占一些独占资源,比如consol或者比如日志文件的写入权限,这样的时候我们一般需要共享一个Lock来对独占资源加锁。

lock作为一个不可直接打包的资源是没有办法作为一个参数直接给Pool的map方法里的函数传参的。

为了解决这个问题,有两种解决方法,一种是使用多进程的管理器Manager(),并使用偏函数的办法传递对象Manager.Lock()。第二种是在进程池创建时传递multiprocessing.Lock()对象。

示例

比如我现在有一个数据列表我想通过多进程的方式将里面的数据发送到指定的API并且在日志文件中记录每次请求所用的时间。

我们最容易想到的解决办法就是把锁作为一个参数传进去:

from multiprocessing import Pool, Lock
import urllib2
from time import clock
from functools import partial
 
def send_request(lock, data):
    api_url = 'http://api.xxxx.com/?data=%s'
    start_time = clock()
    print urllib2.urlopen(api_url % data).read()
    end_time = clock()
    lock.acquire()
    whit open('request.log', 'a+') as logs:
        logs.write('request %s cost: %s\n' % (data, end_time - start_time))
    lock.release()
 
if __name__ == '__main__':
    data_list = ['data1', 'data2', 'data3']
    pool = Pool(8)
    lock = Lock()
    partial_send_request(send_request, lock=lock)
    pool.map(partial_send_request, data_list)
    pool.close()
    pool.join()

在这样的情况下,lock作为一个不可直接打包的资源是没有办法作为一个参数直接给Pool的map方法里的函数传参的。

会出现一个运行时错误:Runtime Error: Lock objects should only be shared between processes through inheritance.

根据一开始的思路我们可以把代码改成下面的样子:

第一种思路,使用Manager。

send_request函数不用改变,只改变main中的内容:

'''
学习中遇到问题没人解答?小编创建了一个Python学习交流QQ群:153708845
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
if __name__ == '__main__':
 
    from multiprocessing import Manager
 
    data_list = ['data1', 'data2', 'data3']
    pool = Pool(8)
    manager = Manager()
    lock = manager.Lock()
    partial_send_request(send_request, lock=lock)
    pool.map(partial_send_request, data_list)
    pool.close()
    pool.join()

这是第一种方法,但是对于仅仅需要一个日志写入锁就用一个Manager显的十分重了。这种方式其实是需要一个专门的进程去处理Manager服务。所有的加锁和释放锁的操作都是通过IPC传递给Manager服务的。

第二种解决思路就是通过initializer参数在Pool对象创建时传递Lock对象。这种方式将Lock对象变为了所有子进程的全局对象。

代码可以作如下修改:

def send_request(data):
    api_url = 'http://api.xxxx.com/?data=%s'
    start_time = clock()
    print urllib2.urlopen(api_url % data).read()
    end_time = clock()
    lock.acquire()
    whit open('request.log', 'a+') as logs:
        logs.write('request %s cost: %s\n' % (data, end_time - start_time))
    lock.release()
def init(l):
    global lock
    lock = l
 
if __name__ == '__main__':
    data_list = ['data1', 'data2', 'data3']
    lock = Lock()
    pool = Pool(8, initializer=init, initargs=(lock,))
    pool.map(send_request, data_list)
    pool.close()
    pool.join()

这样的修改就没有使用偏函数的必要了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值