python进程池与线程池

为什么会进行池化?

一切都是为了效率,每次开启进程都会分配一个属于这个进程独立的内存空间,开启进程过多会占用大量内存,系统调度也会很慢,我们不能无限的开启进程。

进程池原来大概如下图

 

假设有100个任务 ,如果不使用进程池就需要创建100个进程。但是使用进程池假设进程池里有25个进程,那么100个任务 每个都从进程池分配一个进程执行,如果进程池为空就会等待别的任务完成归还进程再分配进程执行任务。

更高级的进程池,会根据任务数量自动收缩和扩充进程池大小,不过python暂时不具备。我猜的原因是因为python效率过低自动化进程池收缩和分配进程会严重影响效率还不如固定大小的进程池效率高。不过可以可以写一个C语言的自动化进程池再联合编程为python模块=。=最近已经在研究C语言希望能搞一搞。

python池化模块

python3.2版本发布的concurrent.futures 模块 ,可以用来生成进程池和线程池。 也可以直接使用multiprocessing.Pool 这里不多介绍了。建议使用前一个毕竟都是标准库模块前一个功能更强。

ProcessPoolExecutor进程池
ThreadPoolExecutor线程池

基本方法:
submit(fn,*args,**kwargs) 异步提交任务 需要使用for循环提交多个任务

map(func,*iterables,timeout=None,chunksize=1) 取代for循环submit的操作

shutdown(wait=True) 相当于进程池pool.close()+pool.join() 操作,wait=True等待池内所有任务执行完毕回收完资源后才继续否则立即返回。但是不管wait为何值程序都会等等所有任务执行完毕。
submit和map必须在shutdown之前

result(timeout=None)取回结果

add_done_callback(fn) 回调函数

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor

def fun1(i):
    print(i)


if __name__ == "__main__":
    p = ProcessPoolExecutor(max_workers=5) #进程池

    for i in range(100):
        p.submit(fun1,i)

    p.shutdown() #回收完所有进程才向下执行

    t = ThreadPoolExecutor(max_workers=5) #线程池
    for item in range(100):
        t.submit(fun1,item)
    print("主进程结束")

拿到返回值

from concurrent.futures import ProcessPoolExecutor

def fun1(i):
    return i

if __name__ == "__main__":
    p = ProcessPoolExecutor(max_workers=5) #进程池

    p_lst = []
    for i in range(100):
        pn = p.submit(fun1,i)
        p_lst.append(pn)
    p.shutdown() #回收完所有进程才向下执行

    result_lst = [task.result() for task in p_lst]
    print(result_lst)   #返回值列表

使用回调函数

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor

def fun1(i):
    return i

def call_back(m):  #回调函数传入的参数是任务的返回值
    print("结果是%d"%m.result())  #处理任务的返回值

if __name__ == "__main__":
    p = ProcessPoolExecutor(max_workers=5) #进程池

p_lst = []

  for i in range(100):
pn
= p.submit(fun1,i).add_done_callback(call_back) #添加回调函数
p_lst.append(pn) p.shutdown()
#回收完所有进程才向下执行

print("主进程结束")

使用上下文管理器

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor

def fun1(i):
    print(i)


if __name__ == "__main__":
    with ProcessPoolExecutor(max_workers=5) as p:  #进程池
        for i in  range(10):
            p.submit(fun1,i)


    with ThreadPoolExecutor(max_workers=5) as t:  #线程池
        for i in range(10):
            t.submit(fun1, i)
View Code

 

使用map方法处理任务

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor

def fun1(i):
    print(i)
    return i*i


if __name__ == "__main__":
    with ProcessPoolExecutor(max_workers=5) as p:  #进程池
        results = p.map(fun1,range(10)) #map的可迭代对象参数的每个值都传入函数执行

        for result in results:
            print(result)    #拿到map的返回值

 

 




posted on 2019-07-03 16:38  thotf  阅读(286)  评论(0)    收藏  举报

导航