day30-2018-12-3-进程
一.什么是进程
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。我们自己在python文件中写了一些代码,这叫做程序,运行这个python文件的时候,这叫做进程。
明朝万历年间,丰田秀吉派兵攻占朝鲜,这时明朝就派了几个将领分别带领了多只部队进行战斗,我们假设一只部队就是一个进程,他的创建是要费时费力的,,他们的目的就是把日本鬼子赶出朝鲜.线程又是啥呢?这只部队肯定分有做饭的,运粮草的,还有啥神机营,开枪打炮的,步兵,骑兵,弓兵,我们可以理解这是线程,真正执行打仗的就是这些线程的,进程就是这些线程的集合.
二.创建
1.通过实例化对象
from multiprocessing import Process
p=Process(target=func,args=(,))
import time import os from multiprocessing import Process def func1(): time.sleep(2) print('我是func1') def func2(): time.sleep(3) print('我是func2') print('子进程的pid',os.getpid()) #查看当前进程的id print('子进程的父进程>>>',os.getppid()) #查看父进程的id if __name__ == '__main__': print('主进程的pid',os.getpid()) print('当前主进程的父进程>>>',os.getppid()) start_time = time.time() p = Process(target=func2,) p.start() #告诉操作系统,我这边准备好了,你帮我创建并执行这个进程 func1() end_time = time.time() dif_time = end_time - start_time print('>>>>',dif_time) p.join() # func1() # func2()
二,通过创建自己类,并继承Process类,实现run 方法
import time from multiprocessing import Process # p = Process(target=func1,args=(1,)) #第二种创建方式 class MyProess(Process): def __init__(self,n): super().__init__() self.n = n def run1(self): time.sleep(2) print(self.n) # def run(self): # time.sleep(2) # print(self.n) # print('aaaaa') if __name__ == '__main__': p = MyProess(10) # p.start() # print('主进程结束')
三.进程间是空间隔离的
import time from multiprocessing import Process num = 100 def func1(): global num time.sleep(1) num = num - 1 print('>>>>>>>>',num) # time.sleep(0.02) # print('来玩啊') # def func2() if __name__ == '__main__': p_list = [] for i in range(10): p = Process(target=func1,) p.start() p.join() p_list.append(p) for pp in p_list: pp.join() # print(num) # p.join() # p.join() print('主进程的num>>>>>',num) print('主进程结束')
四.进程的关闭
#进程对象的其他方法一:terminate,is_alive from multiprocessing import Process import time import random class Piao(Process): def __init__(self,name): self.name=name super().__init__() def run(self): print('%s is 打飞机' %self.name) time.sleep(2) # s = input('???') #别忘了再pycharm下子进程中不能input输入,会报错EOFError: EOF when reading a line,因为子进程中没有像我们主进程这样的在pycharm下的控制台可以输入东西的地方 print('%s is 打飞机结束' %self.name) if __name__ == '__main__': p1=Piao('太白') p1.start() p1.terminate()#关闭进程,不会立即关闭,有个等着操作系统去关闭这个进程的时间,所以is_alive立刻查看的结果可能还是存活,但是稍微等一会,就被关掉了 print(p1.is_alive()) #结果为True print('等会。。。。') time.sleep(1) print(p1.is_alive()) #结果为False
五 锁
import time from multiprocessing import Process,Lock def show_ticket(): with open('test','r',encoding='utf-8') as f: time.sleep(0.1) num = f.read().strip() print('客户查看到的剩余票数:',num) def func1(i,loc): show_ticket() print('准备开始抢锁') time.sleep(1) loc.acquire() with open('test','r',encoding='utf-8') as f: time.sleep(0.1) num = f.read().strip() # print('%s客户查看到的剩余票数:'%i,num) if num == '0': print('没票了') else: num = int(num) num -= 1 time.sleep(0.05) with open('test','w',encoding='utf-8') as f: f.write(str(num)) print('客户%s抢到票了'%i) loc.release() if __name__ == '__main__': loc = Lock() #创建了一把锁 for i in range(10): p = Process(target=func1,args=(i,loc,)) p.start()
六.信号量
from multiprocessing import Process,Semaphore import time,random def func(i,s): s.acquire() print('男%s号大宝剑开始'%i) time.sleep(2) print('%s号嘉宾结束了'%i) time.sleep(1) s.release() if __name__ == '__main__': s = Semaphore(4) for i in range(10): p = Process(target=func,args=(i,s,)) p.start()
七.事件
from multiprocessing import Process,Event e = Event() #两个状态,True False,默认是状态False print('开始啦') print(e.is_set()) #查看事件对象的当前状态 e.set() #将事件对象的状态改为True print('>>>>',e.is_set()) #查看事件对象的当前状态 e.clear() #将事件状态改为False print('状态为False了') e.wait() # print('结束啦')
八.守护进程
import time from multiprocessing import Process def func1(): time.sleep(2) print('xxxxx') if __name__ == '__main__': p = Process(target=func1,) p.daemon = True #守护进程,要写在start之前 p.start() print('主进程代码运行完了') # time.sleep(3)
九.队列
from multiprocessing import Queue q = Queue(3) #先进先出 fifo first in first out,队列里面的数据,只能取一次 q.put(1) q.put(2) #添加数据 # print('>>>>>>>',q.full()) #不可信的 q.put(3) # print('>>>>>>>',q.full()) # print(q.get()) # print('>>>>',q.empty())#不可信 print(q.get()) # print(q.get()) print('>>>>',q.empty()) print('-----------') # print(q.get()) try: s = q.get_nowait() #queue.Empty print('====',s) except: print('队列空了,去搞别的吧') # q.get(False) # q.put(4)
十.基于队列的进程通信
from multiprocessing import Process,Queue def func1(q): res = q.get() print('>>>>>>',res) if __name__ == '__main__': q = Queue(5) q.put('约吗亲') p = Process(target=func1,args=(q,)) p.start() print('主进程结束') #队列是进程安全的,数据安全,底层有个锁,队列里面的数据只能取一次
十一.生产者消费者模式
import time from multiprocessing import Process,Queue #生产者 def producer(q): for i in range(10): time.sleep(1) q.put('包子%s号'%i) print('包子%s号生产完毕'%i) q.put(None) def consumer(q): while 1: baozi = q.get() if baozi == None: break time.sleep(1.5) print('%s被吃掉了'%baozi) if __name__ == '__main__': q = Queue(10) p1 = Process(target=producer,args=(q,)) p2 = Process(target=consumer,args=(q,)) p1.start() p2.start()
十二.joinablequeue队列
from multiprocessing import Process,JoinableQueue import time,random,os def consumer(q): while True: res=q.get() # time.sleep(random.randint(1,3)) time.sleep(random.random()) print('\033[45m%s 吃 %s\033[0m' %(os.getpid(),res)) q.task_done() #向q.join()发送一次信号,证明一个数据已经被取走并执行完了 def producer(name,q): for i in range(10): # time.sleep(random.randint(1,3)) time.sleep(random.random()) res='%s%s' %(name,i) q.put(res) print('\033[44m%s 生产了 %s\033[0m' %(os.getpid(),res)) print('%s生产结束'%name) q.join() #生产完毕,使用此方法进行阻塞,直到队列中所有项目均被处理。 print('%s生产结束~~~~~~'%name) if __name__ == '__main__': q=JoinableQueue() #生产者们:即厨师们 p1=Process(target=producer,args=('包子',q)) p2=Process(target=producer,args=('骨头',q)) p3=Process(target=producer,args=('泔水',q)) #消费者们:即吃货们 c1=Process(target=consumer,args=(q,)) c2=Process(target=consumer,args=(q,)) c1.daemon=True #如果不加守护,那么主进程结束不了,但是加了守护之后,必须确保生产者的内容生产完并且被处理完了,所有必须还要在主进程给生产者设置join,才能确保生产者生产的任务被执行完了,并且能够确保守护进程在所有任务执行完成之后才随着主进程的结束而结束。 c2.daemon=True #开始 p_l=[p1,p2,p3,c1,c2] for p in p_l: p.start() p1.join() #我要确保你的生产者进程结束了,生产者进程的结束标志着你生产的所有的人任务都已经被处理完了 p2.join() p3.join() print('主')
十三.管道
管道
from multiprocessing import Pipe,Process def func(conn1,): # conn2.close() msg = conn1.recv() print('>>>>>',msg) if __name__ == '__main__': conn1,conn2 = Pipe() p = Process(target=func,args=(conn1,)) p.start() # conn1.close() conn2.close() conn2.send('小鬼!') print('主进程结束') #EOFError #OSError
注意:主进程和子进程之间的通信通过 同一根管子的conn1 口和conn2口通信的,但是主进程关了conn1口 ,并不导致子进程的conn1不能用,也就是口是各自的,管子是公用的
十四.数据共享
from multiprocessing import Process,Manager,Lock def func(dic,loc): # loc.acquire() # with loc: dic['num'] -= 1 # tmp = dic['num'] # tmp = tmp - 1 # dic['num'] = tmp # loc.release() if __name__ == '__main__': m = Manager() loc = Lock() dic = m.dict({'num':100}) p_list = [] for i in range(100): p = Process(target=func,args=(dic,loc)) p_list.append(p) p.start() [pp.join() for pp in p_list] print('>>>>>',dic['num'])
十五.进程池
import time from multiprocessing import Process,Pool def func(i): num = 0 for j in range(5): num += i if __name__ == '__main__': pool = Pool(4) # p_list = [] start_time = time.time() for i in range(500): p = Process(target=func,args=(i,)) p_list.append(p) p.start() [pp.join() for pp in p_list] end_time = time.time() print(end_time - start_time) s_time = time.time() pool.map(func,range(500)) #map e_time = time.time() print(e_time - s_time)
十六.进程同步的方法
import time from multiprocessing import Process,Pool def func(i): num = 0 for j in range(5): num += i time.sleep(1) # print(num) return num if __name__ == '__main__': pool = Pool(4) for i in range(10): res = pool.apply(func,args=(i,)) # print(res) # apply
十七.进程池的异步处理
import time from multiprocessing import Process,Pool def func(i): num = 0 for j in range(5): num += i time.sleep(1) # print('>>>>>',num) return num if __name__ == '__main__': pool = Pool(4) red_list = [] for i in range(10): res = pool.apply_async(func,args=(i,)) # # print(res) red_list.append(res) # print(res.get()) # pool.close() #不是关闭进程池,只是锁定 # pool.join() # 等待进程池中所有的任务执行完,但是无法确认是否所有的任务真的全部执行完了,前面要加close方法 for resss in red_list: print(resss.get())
十八.回调函数
import time from multiprocessing import Pool,Process import os def func(n): # print('xxxxxxxxxx') print('子进程的pid',os.getpid()) return n*n,'约吗' def call_back_func(x): # print(x) #(9, '约吗') print('call_back',os.getpid()) print(x[0]) if __name__ == '__main__': pool = Pool(4) pool.apply_async(func,args=(3,),callback=call_back_func) # print('主进程的pid',os.getpid()) # pool.close() # pool.join() # time.sleep(1)
十九.文件对象的获取
import sys class MyClass(): def func(self): print('xxxxx') # pass file_obj = sys.modules['__main__'] print(file_obj) print(file_obj.__dict__['MyClass']().func())