python多进程multiprocessing模块

 

使用模块提供了一个Process类实现多进程:

创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动;

join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步;

使用Process不需要close()直接join()就行。

from multiprocessing import Pool, Process, Queue
import os, time, random

def long_time_task(name, q):
    print('Run task %s (%s)...' % (name, os.getpid()))
    q.put({"TaskName": name, "pid": os.getpid()})
    start = time.time()
    time.sleep(random.random()*3)
    end = time.time()
    print('Task %s runs %0.2f seconds.' % (name, (end - start)))

if __name__=='__main__':
    print('Parent process %s.' % os.getpid())
    q = Queue()
    for i in range(5):
        p = Process(target=long_time_task, args=(i, q))
        p.start()
        p.join()
    print('Waiting for all subprocesses done...')
    # p.close()
    for i in range(q.qsize()):
        print(q.get())
    print('All subprocesses done.')

 

运行结果

Parent process 3424.
Run task 0 (6880)...
Task 0 runs 1.21 seconds.
Run task 1 (7344)...
Task 1 runs 1.84 seconds.
Run task 2 (5572)...
Task 2 runs 1.56 seconds.
Run task 3 (6316)...
Task 3 runs 0.67 seconds.
Run task 4 (6196)...
Task 4 runs 2.83 seconds.
Waiting for all subprocesses done...
{'TaskName': 0, 'pid': 6880}
{'TaskName': 1, 'pid': 7344}
{'TaskName': 2, 'pid': 5572}
{'TaskName': 3, 'pid': 6316}
{'TaskName': 4, 'pid': 6196}
All subprocesses done.

Process finished with exit code 0

Pool类

Pool类可以提供指定数量的进程供用户调用,当有新的请求提交到Pool中时,如果池还没有满,就会创建一个新的进程来执行请求。如果池满,请求就会告知先等待,直到池中有进程结束,才会创建新的进程来执行这些请求。

Pool 中提供了如下几个方法:

apply()
apply_async()
map()
map_async()
close()
terminal()
join()

apply和apply_async的区别:

apply方法是阻塞的:
首先主进程开始运行,碰到子进程,操作系统切换到子进程,等待子进程运行结束后,在切换到另外一个子进程,直到所有子进程运行完毕。然后在切换到主进程,运行剩余的部分。

apply_async 是异步非阻塞的:

首先主进程开始运行,碰到子进程后,主进程说:让我先运行个够,等到操作系统进行进程切换的时候,在交给子进程运行。以为我们的程序太短,然而还没等到操作系统进行进程切换,主进程就运行完毕了。

想要子进程执行,就告诉主进程:你等着所有子进程执行完毕后,在运行剩余部分。(p.close(), p.join())

p.close()关闭进程池,不再往进程池中添加新的进程。

 

python官方建议:废弃apply,使用apply_async。

使用POOL进程池的时候,Queue对象队列不能直接作为参数传递:

队列对象不能在父进程与子进程间通信,这个如果想要使用进程池中使用队列则要使用multiprocess的Manager类

    manager = multiprocessing.Manager()
    q = manager.Queue()

这样这个队列对象就可以在父进程与子进程间通信,不用池则不需要Manager。

关于锁的应用:

在不同程序间如果有同时对同一个队列操作的时候,为了避免错误,可以在某个函数操作队列的时候给它加把锁,这样在同一个时间内则只能有一个子进程对队列进行操作,锁也要在manager对象中的锁。

#coding:gbk
 
from multiprocessing import Process,Queue,Pool
import multiprocessing
import os, time, random
 
# 写数据进程执行的代码:
def write(q,lock):
    lock.acquire() #加上锁
    for value in ['A', 'B', 'C']:
        print 'Put %s to queue...' % value        
        q.put(value)        
    lock.release() #释放锁  
 
# 读数据进程执行的代码:
def read(q):
    while True:
        if not q.empty():
            value = q.get(False)
            print 'Get %s from queue.' % value
            time.sleep(random.random())
        else:
            break
 
if __name__=='__main__':
    manager = multiprocessing.Manager()
    # 父进程创建Queue,并传给各个子进程:
    q = manager.Queue()
    lock = manager.Lock() #初始化一把锁
    p = Pool()
    pw = p.apply_async(write,args=(q,lock))    
    pr = p.apply_async(read,args=(q,))
    p.close()
    p.join()
    
    print
    print '所有数据都写入并且读完'

 

参考文章:

http://python.jobbole.com/86181/

https://www.cnblogs.com/wangqiaomei/p/5682669.html

https://blog.csdn.net/pzqingchong/article/details/79683251

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值