更方便的进程管理工具Multiprocessing

更方便的管理进程
multiprocessing
步骤
1. 确定执行事件,将事件封装成函数 
2. 使用Process 创建新的进程,将要执行的函数传入
   的到相应的进程对象
	 ***************************************
	 Process 参数 
	 name : 起的新的进程名称
	 target: 传入的目标函数
	 args: 以元组的方式向目标函数进行位置传参
	 kwargs:以字典的方式向目标函数进行传参
	 ***************************************
3.使用相应的对象调用start()属性函数启动子进程
4.使用响应对象调用 join()函数等待接受子进程退出
*************************************
import multiprocessing as mp
import os
from time import sleep
from random import randint


#定义函数
def worker():
    sleep(randint(0,4))
    print(os.getppid(),'-------',\
        os.getpid())
    print('worker')


jobs = []


print('This is parent:',os.getpid())
for i in range(5):
    p = mp.Process(target = worker)
    jobs.append(p)
    p.start()
    
for i in jobs:
    i.join()
进程对象 p 的属性
p.pid  响应子进程的PID号
p.name  子进程的 名字
p.is_alive() : 子进程状态
p.start() : 启动子进程
p.join([timeout]): 回收子进程函数 timeout是一个可选参数,表示超时等待时间。
import multiprocessing as mp 
from time import sleep
import os 


a = 100


def worker(sec,message):
    for i in range(3):
        sleep(sec)
        print('the create message:',\
            message)
        print('in child process:',\
            os.getppid())
    print(a)


p = mp.Process(target = worker,\
    name = 'Ketty',args = (2,),\
    kwargs = {'message':'hello world'})


p.start()
print('pid:',p.pid) #子进程的PID
print('name:',p.name) #子进程的名字
print('is_alive',p.is_alive()) #状态
a = 100000


p.join() #等待3秒,如果不退出就不等了
print('*****main process over******')
print(a)
p.daemon :  默认为False  表示主进程执行结束后不会立即退出,而是等待子进程执行结束后再退出。
设置为 True ,那么主进程执行结束后会终止该子进程的执行,并且立即退出。必须在start前设置
run()
import multiprocessing as mp
from time import sleep 


def fun():
    print('child start')
    sleep(3)
    print('fun is over')


p = mp.Process(target = fun)
p.daemon = True 
p.start()
sleep(0.1)
print("***main process over*****")
守护进程:系统中的后台服务进程。

特点:独立于终端并周期性的执行某种任务
      生命周期长,一般随系统启动,随系统终止

进程缺点

进程的创建需要消耗较多的系统资源

进程池

多个进程执行任务
任务非常多,且执行时间短,需要频繁创建删除进程

1. 使用 Pool 创建进程池,得到进程池对象
2. 使用 apply_async 将事件放入进程池等待执行
3. 如果池内有空闲进程则会执行等待的事件
4. 使用close关闭进程池,不能够在投放进程
5. 使用join 阻塞等待进程池内现有所有事件都被执行结束后回收子进程(进程池内所有进程均为子进程)

进程池对象(pool)的方法:

异步加载事件到进程池
pool.apply_async(fun,[args = (),[kwargs = {}]])

同步加载事件到进程池
pool.apply(fun,[args = (),[kwargs = {}]])

close()  关闭进程池

join()  阻塞,等待进程池子进程退出。必须在close
        后

import multiprocessing as mp 
from time import sleep 
import os 


def worker(msg):
    print(os.getpid())
    sleep(2)
    print(msg)
    return


if __name__ == '__main__':
    #创建一个包含四个进程的进程池,得到进程池对象pool
    pool = mp.Pool(processes = 4)
    result = [] 
    for i in range(10):
        msg = 'hello %d'%i 
        #向进程池中加载事件
        # r = pool.apply(worker,(msg,)) #同步执行
        r = pool.apply_async(worker,(msg,))
        result.append(r)
    # 得到每个事件的返回值 ,apply方法没有此功能   
    for res in result:
        print(res.get())
   
    #关闭进程池
    pool.close()  
    #进程池回收
    pool.join()
  

pool.map(fun, iterable)
功能上类似内建函数 map 将第二个参数中的每一个数带入到第一函数中进行传参。然后将该事件放入进程池


进程间通信

不同的进程间进行消息的传递。

文件 : 不好 , 文件可以被随意打开修改。和磁盘的交互也比较慢

管道 :

在内存中开辟的一块空间,对多个进程可见。在形式上有一定的约束。

* 通过 Pipe 创建,返回值有两个分别表示管道的两端。
* 当创建时参数为True(默认)时两个返回值均可以进行send和recv操作,当为false时,第一个可进行recv操作第二个可send。
* recv函数为阻塞函数,当管道内为空时会阻塞

import time 
from multiprocessing import Pool 


def run(fn):
    time.sleep(1)
    return fn*fn 


test = [1,2,3,4,5,6]


print('顺序执行:')


s = time.time()
for fn in test:
    run(fn)   
e = time.time()
print('执行时间:',float(e - s))


print('多任务执行:')


pool = Pool(3)


# 兼顾了 apply_async 
r = pool.map(run,test)
pool.close()
pool.join()
e1 = time.time()
print('执行时间:',float(e1 - e))

猜你喜欢

转载自blog.csdn.net/weixin_41802988/article/details/80221602