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 Process
import os
def 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 Pool
import os,time,random
def run(name):
print('prcess%s(%s)'% (name,os.getpid()))
time.sleep(random.random()*3)
print('end %s'% name)
return name
def 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 Pool
import os,time,random
def run(name):
print('prcess%s(%s)'% (name,os.getpid()))
time.sleep(random.random()*3)
print('end %s'% name)
return name
def 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次任务会被新的进程替代