进程池
在使用Python进行系统管理时,特别是同时操作多个文件目录或者远程控制多台主机,并行操作可以节约大量的时间。如果操作的对象数目不大时,还可以直接使用Process类动态的生成多个进程,十几个还好,但是如果上百个甚至更多,那手动去限制进程数量就显得特别的繁琐,此时进程池就派上用场了。Pool类可以提供指定数量的进程供用户调用,当有新的请求提交到Pool中时,如果池还没有满,就会创建一个新的进程来执行请求。如果池满,请求就会告知先等待,直到池中有进程结束,才会创建新的进程来执行这些请求。
Pool类中方法
apply():
函数原型:apply(func[, args=()[, kwds={}]])
该函数用于传递不定参数,主进程会被阻塞直到函数执行结束(不建议使用,并且3.x以后不再使用)。
map()
函数原型:map(func, iterable[, chunksize=None])
Pool类中的map方法,与内置的map函数用法行为基本一致,它会使进程阻塞直到返回结果。
注意,虽然第二个参数是一个迭代器,但在实际使用中,必须在整个队列都就绪后,程序才会运行子进程。
返回结果为一个list,序列传入func后执行结果的list;

close()
关闭进程池(Pool),使其不再接受新的任务。

terminate()
立刻结束工作进程,不再处理未处理的任务。

join()
使主进程阻塞等待子进程的退出,join方法必须在close或terminate之后使用。

获取CPU的核数
multiprocessing.cpu_count() #获取cpu的核数

创建进程池
示例1:
#coding=utf-8
import multiprocessing
import os,time
import random
def m1(x):
    time.sleep(random.random() * 4)
    print("pid: ",os.getpid(), x*x)
    return x*x

if __name__ == "__main__":
    pool = multiprocessing.Pool(multiprocessing.cpu_count())
    i_list = range(8)
    res =pool.map(m1,i_list)#函数
    print (type(res))
    print(res)



示例2:
#coding=utf-8
import multiprocessing
import os,time
import random
def f(x):
    return x * x

if __name__ == "__main__":
pool = multiprocessing.Pool(processes = 4)
#执行进程池中的一个子进程,执行结果存放在result中
result = pool.apply_async(f,[10])

print(result.get(timeout=1))#获取执行结果

#多进程执行进程池中的进程
print(pool.map(f,range(10)))




多进程与单进程执行时间比较

#coding=utf-8
import time
from multiprocessing import Pool
def run(fn):
    time.sleep(1)
    return fn*fn

if __name__ == "__main__":
    testFL = [1,2,3,4,5,6]
    print("单进程执行: ")
    start = time.time()
    
    for fn in testFL:
        run(fn)

    end = time.time()
    print("顺序执行时间: ",end - start)

    pool = Pool(5)#创建包含5个进程的进程池
    t = time.time()
    res = pool.map(run,testFL)
    pool.close()#关闭进程池,不再接受新的任务
    pool.join()#等待子进程执行结果退出
    end = time.time()
    print("进程池并行执行时间: ",end - t)
print(res)


Multiprocessing.Queue方法
>>> q = Queue()
>>> q.put(1)
>>> q.put(1)
>>> q.put(2)
>>> q.get()
1
>>> q.qsize()
2
>>> q.empty()
False
>>> q.full()
False
>>> q.get(timeout=1)
1
>>> q.get()
2

同步进程
使用Queue 同步进程间数据
示例1:

#coding=utf-8
from multiprocessing import Queue,Process
def func(queue):
    queue.put("通过队列同步的消息!")

if __name__ == "__main__":
    q = Queue()#此处队列q为主进程的
p = Process(target = func,args=(q,))
#主进程、子进程是两个独立的进程,数据不共享
#生成子进程,通过主进程定义的队列q同步主、子进程消息
    p.start()
    p.join()
print("主进程和子进程同步的队列消息:",q.get())#获取同步的队列数据



multiprocessing.Queue类似于queue.Queue,一般用来多个进程间交互信息。Queue是进程和线程安全的。它实现了queue.Queue的大部分方法,但task_done()和join()没有实现。multiprocessing.JoinableQueue是multiprocessing.Queue的子类,增加了task_done()方法和join()方法。task_done():用来告诉queue一个task完成。一般在调用get()时获得一个task,在task结束后调用task_done()来通知Queue当前task完成。join():阻塞直到queue中的所有的task都被处理(即task_done方法被调用)。

示例2:
#coding=utf-8
from multiprocessing import Process,Queue
import random,time
def write(q):
    for value in ["A","B","C"]:
        print("Put %s to queue." %value)
        q.put(value)
        time.sleep(random.random())


def read(q):
    time.sleep(1)
    while not q.empty():
        print("Get %s from queue." %q.get(True))


if __name__ == "__main__":
    q = Queue()#主进程定义的队列
    p1 = Process(target=write,args=(q,))#两个子进程同步进程数据
    p2 = Process(target=read,args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print("Done!")


示例3:
进程池间同步数据需要使用Manager里面的Queue
#encoding=utf-8
from multiprocessing import Pool,Manager
def func(q):
    print("*"*10)
    q.put("12346")

if __name__ == "__main__":
   manager = Manager()
   q = manager.Queue()
   pool = Pool(processes=4)
   for i in range(5):
       pool.apply_async(func,(q,))
   
   pool.close()
   pool.join()
   print(q.qsize())