python 的进程、线程以及协程(1)

来源:互联网 发布:环保部水质检测数据 编辑:程序博客网 时间:2024/06/06 03:16

python 的进程、线程以及协程(1)

简书ID 真三泥
python实现多进程主要有两种,一种是os模块的fork方法,另一种是multiprocessing,他们的区别在于第一种仅适用Unix/linux,对win不支持,后者是跨平台的.

multiprocessing模块创建多线程:

通过实现Process类来创建:Process(group=None,target=None,name=None,args=(),kwargs={})

参数说明:
target:表示这个进程实例所调用对象

args:表示调用对象的位置参数元组;

kwargs:表示调用对象的关键字参数字典;

name:为当前进程实例的别名;

group:大多数情况下用不到;
Process类常用方法:

is_alive():判断进程实例是否还在执行;

join([timeout]):是否等待进程实例执行结束,或等待多少秒;

start():启动进程实例(创建子进程);

run():如果没有给定target参数,对这个对象调用start()方法时,就将执行对象中的run()方法;

terminate():不管任务是否完成,立即终止;

实例

代码块

from multiprocessing import Processimport osdef run(name,height=0,weight=0):    print("process %s:%s,height:%s,weight:%s"% (name, os.getpid(), height, weight))if__name__  == '__main__':    for i in range(8):        p = Process(target=run, args=(str(i),), kwargs={'height':100,'weight':50})        print('process will start')        p.start()p.join()# 实现进程的同步,等待最后子进程结束,如果不加的这个语句可能会出现主进程结束而子进程没有结束,因为主进程结束导致未完成的主进程结束print('process end')

进程池pool:

multiprcessing 提供了 Pool类来代表进程池对象,Pool 可以提供指定的进程提供用户调用,默认是cpu的核数。但有新的请求提交到pool时 如果池没有满,就创建,如果满了,就会等待,直到有进程结束,才会创建新的进程来处理.

Pool(processes=None,initializer=None,initargs(),maxtasksperchild=None,context=None)
参数说明:
processes:进程池最大个数,如果是None,通过返回的数字os.cpu_count()被使用(默认是cpu的核数)

initializer:如果不是None,那么将在将启动每个工作进程时调用initializer( initargs)。*

maxtasksperchild:一个工作进程在它退出之前完成的任务的数量,被一个新的工作 进程所取代,从而使未使用的资源得到释放,默认的maxtasksperchild是None,这意味着工作进程将与池一样长
(允许在池内的工作进程在退出前只完成一定数量的工作,然后进行清理,并生成新的进程来替换旧的工作)

context:可以用来指定启动工作进程所用的上下文。通常,池是使用函数multiprocess. pool()或上下文对象的pool()方法创建的。在这两种情况下都适当地设置了上下文。

常用方法:

apply(func[, args=()[, kwds={}]]):
往进程池添加任务进程.不太常用用,使用apply()进程会被阻塞直到函数执行结束

apply_async(func[,args[,kwds[,callback[,error_callback]]]]):
apply_async()是apply()函数的变体,如果指定callback,callback应该是一个可以接受单个参数的函数接收func返回值,在调用失败,在这种情况下,将使用error_callback,如果指定error_callback,error_callback应该是一个可以接受单个参数的函数,如果目标函数调用失败,则会使用异常实例调用error_callback ( callback应该立即完成,否则处理结果的线程将被阻塞。)

map(func,iterable[,chunksize]):
一个类似于map()内置函数的等价函数(它只支持一个可迭代的参数)。它会使进程阻塞与此直到结果返回 ,返回列表,该方法将迭代分成若干块,并将其提交到进程池作为单独的任务。这些块的(大约)大小可以通过将chunksize设置为一个正整数来指定。

map_async(func, iterable[, chunksize[, callback]])
与map用法一致,但是它是非阻塞的。可以同过返回结果.get()得到进程池返回结果列表

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

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

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

实例代码

from multiprocessing import Poolimport os,time,randomdef run(name):    print('prcess%s(%s)'% (name,os.getpid()))    time.sleep(random.random()*3)    print('end %s'% name)    return namedef run1():    print(1);if __name__ == '__main__':    args = (10, 20, 30)    List = [1,2,3,4,5,6,7,8,9,10,11]    p = Pool(processes=4,initializer=run1,)    result = p.map_async(run,List)    p.close()    p.join()    print('-'*80)

结果
这里写图片描述

from multiprocessing import Poolimport os,time,randomdef run(name):    print('prcess%s(%s)'% (name,os.getpid()))    time.sleep(random.random()*3)    print('end %s'% name)    return namedef run1():    print(1);if __name__ == '__main__':    args = (10, 20, 30)    List = [1,2,3,4,5,6,7,8,9,10,11]    p = Pool(processes=4,initializer=run1,maxtasksperchild=2)    result = p.map_async(run,List)    p.close()    p.join()    print('-'*80)

这里写图片描述

上面的两个结果可以看出每个进程启动前会调用initializer函数,当我设置maxtasksperchild=2的时候可以看出每个进程完成2次任务会被新的进程替代