1 子进程创建
from multiprocessing import Process def func(i): #创建一个带参数的函数,子进程的运行代码都在这里面 print("我是子进程%s" %i) if __name__ == '__main__': #windos 环境下需要加这句 p = Process(target=func,args=(10,)) #args 是用来传递参数的 p.start() # 运行
进程之间是独立的运行互不影响‘
进程的生命周期:从start开始,到子进程中代码运行完结束
os.getpid() 当前进程号
os.getppid() 查看当前进程父进程的进程号
from multiprocessing import Process import os def func(i): #创建一个带参数的函数,子进程的运行代码都在这里面 print("我是子进程%s" %i) print('进程号%s'%os.getpid()) if __name__ == '__main__': #windos 环境下需要加这句 p = Process(target=func,args=(10,)) #args 是用来传递参数的 p.start() # 运行 print('主进程号%s'%os.getppid()) #因为是并发的所以主进程与子进程没有先后顺序
多进程并发与join方法
join方法是在子进程的结束,再执行下面主进程的代码
from multiprocessing import Process import time def func(): print("#"*5) time.sleep(3) print("#"*10) if __name__ == '__main__': p = Process(target=func) p.start() p.join() print("结束")
多程序并发方法一
from multiprocessing import Process import time def func(): print("#"*5) time.sleep(3) print("#"*10) if __name__ == '__main__': p = Process(target=func) p.start() p = Process(target=func) p.start() p = Process(target=func) #可以建立多个子进程 p.start() p.join() print("结束") #子进程之间并发,没有先后顺序,在所有子进程执行完,执行这句
from multiprocessing import Process import time def func(): print("#"*5) time.sleep(3) print("#"*10) if __name__ == '__main__': p_lst = [] for i in range(5): p = Process(target=func) p_lst.append(p) p.start() for p in p_lst: p.join() print("结束")
第二种方法:
#自定义一个类继承process
#必须有一个run方法 子进程执行run中的代码
from multiprocessing import Process import os class fun(Process): #如果想传递参数 def __init__(self,a,b): #初始化 super().__init__() #因为继承的父类里有init self.a = a self.b = b def run(self): # 执行的代码 print(os.getpid()) print(self.a,self.b) if __name__ == '__main__': p1 = fun(1,2) p1.start() p2 = fun(3,4) p2.start()
#使用并发实现socket


import socket from multiprocessing import Process def serve(conn): ret = '你好'.encode('utf-8') conn.send(ret) msg = conn.recv(1024).decode('utf-8') print(msg) conn.close() if __name__ == '__main__' : sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() try: while True: conn,addr = sk.accept() p = Process(target=serve,args=(conn,)) p.start() finally: sk.close()


import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) msg = sk.recv(1024).decode('utf-8') print(msg) msg2 = input('>>>').encode('utf-8') sk.send(msg2) sk.close()
守护进程:
子进程随着主进程的结束而结束
#守护进程随着主进程的代码执行完了结束
p.is_alive() 进程存活返回true 进程结束返回false
p.terminate() 在主进程内结束一个子进程
from multiprocessing import Process import time def func(): while True: time.sleep(0.2) print("我还活着") if __name__ == '__main__': p = Process(target=func) p.daemon=True #设为守护进程 p.start() i = 0 while i < 5: print("是主城粗第%s秒"%i) time.sleep(2) i = i + 1
进程锁
如买票 ,在查看票数显示余票,多个进程并发,给某段代码加上锁,在一段时间内这段代码只能有一个进程执行
锁代码:
from multiprocessing import lock
locl.acquire() #那钥匙
lock.release() 还钥匙


import json from multiprocessing import Process from multiprocessing import Lock def cha(i): with open('ff') as f: dic = json.load(f) print('%s余票:%s'%(i,dic['ticket'])) def gou(i,lock): # 在购票时需要进行锁, lock.acquire() #取钥匙 with open('ff',) as f: #先读取 dic = json.load(f) if dic['ticket'] >= 1: dic['ticket'] = dic['ticket'] - 1 print('\033[32m%s购票成功\033[0m'%i) else: print('\033[31m%s购票失败\033[0m'%i) with open('ff','w') as fx: json.dump(dic,fx) # 将修改的在写入文件中 lock.release() # 还钥匙 if __name__ == '__main__': for i in range(10): p = Process(target=cha,args=(i,)) #查票子进程 p.start() lock = Lock() for i in range(10): p2 = Process(target=gou,args=(i,lock)) p2.start()
信号量:
与锁相同作用锁相同,锁一次只能允许一个
参考博客:www.cnblogs.com/Eva-J/articles/8253549.html
from multiprocessing import Semaphore
sem = Semaphore(4) 实例化下
sem.acquire() 获取钥匙
sem.release() 还钥匙
如 ktv 中 20人同时向进去,但一次只能进去4人
每人唱的时间不一样,只有出来一个,才能再进入一个


from multiprocessing import Process from multiprocessing import Semaphore import time import random def ktv(i,sem): sem.acquire() #获取钥匙 print("%i 进入ktv"%i) time.sleep(random.randint(10,50)) #模拟的没人随机唱的时间 print("%i 走出ktv"%i) sem.release() #还钥匙 #进程实例还 if __name__ == '__main__': sem = Semaphore(4) for i in range(20): p = Process(target=ktv,args=(i,sem)) p.start()
事件
#一个事件可以所有的进程进入阻塞状态
#也可以控制所有的进程解除阻塞
#一个事件被创建之后默认是阻塞状态
from multiprocessing import Event
e = Event() 创建了个事件
e.is_set() 查看一个事件的状态, false 阻塞 返回true 不阻塞
e.wait() 是依据e.is_set 的值决定是否阻塞的执行者 false阻塞 true 不阻塞
e.set() #将事件的状态改为true
e.clear() #将事件状态改为false 阻塞
红绿灯事件:
红灯,绿灯交替出现,在红灯时停止,绿灯时通行
每次通过数量是随机的所以需要random 模块


from multiprocessing import Process import time from multiprocessing import Event import random #定义一个车 def cars(e,i): if not e.is_set(): print('car%i在等待'%i) e.wait() print("car%s 通过了"%i) def light(e): while True: if e.is_set(): #true e.clear() # 改为false print("\033[31m红灯亮了\033[0m") # 阻塞 else: e.set() #改为true print("\033[32m绿灯亮了\033[0m") # 不阻塞 time.sleep(2) if __name__ == '__main__': e = Event() #创建个事件 p = Process(target=light,args=(e,)) p.start() for i in range(20): #定义有20辆车 car = Process(target=cars,args=(e,i)) car.start() time.sleep(random.random()) #每次同时在过来的车不一定
队列
队列用于存放数据,可以实现连个进程之间的通信IPC
from multiprocessing import Queue
q = Queue(5) #设定队列 5 为大小
q.put(i) 放数据 队列满了就会阻塞
q.full() #队列是否满了 true 满
q.get() 取数据 全部取出后阻塞
q.empt() 是否空了 True 空
q.get_nowait() 取值没有值会报错
try:
q.get_nowait()
except:
print("队列空")


from multiprocessing import Queue ,Process def produce(q): q.put('hello') def consume(q): print(q.get()) if __name__ == '__main__': q = Queue() p = Process(target=produce,args=(q,)) p.start() p1 = Process(target=consume,args=(q,)) p1.start()
生产者消费者模型:
#存在消费者与生产者供需不平衡的问题


from multiprocessing import Queue,Process import time import random def produce(name,food,q): for i in range(10): time.sleep(random.randint(1,3)) f = '%s生产了%s%s'%(name,food,i) print(f) q.put(f) def consumer(q,name): while True: food = q.get() if food is None: break print("%s消费了%s"%(name,food)) time.sleep(random.randint(1, 3)) if __name__ == '__main__': q = Queue() p = Process(target=produce,args=('xiao','包子',q)) p.start() c = Process(target=consumer,args=(q,"long")) c.start() p.join() # 感知生产者的结束 q.put(None)
JoinableQueue 也是一个队列
每次在获取一个数值时会给队列一个回值
q.task_done() 回值


#存在消费者与生产者供需不平衡的问题 from multiprocessing import JoinableQueue,Process import time import random def produce(name,food,q): for i in range(10): time.sleep(random.randint(1,3)) f = '%s生产了%s%s'%(name,food,i) print(f) q.put(f) q.join() #阻塞等到所有数都被处理完,才结束 def consumer(q,name): while True: food = q.get() print("%s消费了%s"%(name,food)) time.sleep(random.randint(1, 3)) q.task_done() if __name__ == '__main__': q = JoinableQueue() p = Process(target=produce,args=('xiao','包子',q)) p.start() c = Process(target=consumer,args=(q,"long")) c.daemon=True #守护进程主进程中的代码运行完后,子进程自动结束 c.start() p.join() # 感知生产者的结束 # 在消费者这一端: # 每次获取一个数据 # 处理一个数据 # 发送一个记号 : 标志一个数据被处理成功 # 在生产者这一端: # 每一次生产一个数据, # 且每一次生产的数据都放在队列中 # 在队列中刻上一个记号 # 当生产者全部生产完毕之后, # join信号 : 已经停止生产数据了 # 且要等待之前被刻上的记号都被消费完 # 当数据都被处理完时,join阻塞结束 # consumer 中把所有的任务消耗完 # producer 端 的 join感知到,停止阻塞 # 所有的producer进程结束 # 主进程中的p.join结束 # 主进程中代码结束 # 守护进程(消费者的进程)结束
管道:用于进程之间通信
from multiprocessing import Pipe
返回两个参数
conn1,conn2 = Pipe()
conn1.send('12345') #进程conn1 发送数据
print(conn2.recv()) # 进程conn2 接受
from multiprocessing import Pipe,Process def func(conn): conn.send("吃了吗") if __name__ == '__main__': conn1,conn2 = Pipe() p = Process(target=func,args=(conn1,)) p.start() print(conn2.recv())
from multiprocessing import Pipe,Process def func(conn1,conn2): conn2.close() #不需要conn2,所以将其关闭 while True: try: msg = conn.recv() print(msg) except EFError: #没有数据取出的会报错,这里用try语句,报错退出 conn1.close() break if __name__ == '__main__': conn1,conn2 = Pipe() p = Process(target=func,args=(conn1,conn2)) p.start() conn1.close() for i in range(20): conn2.send("吃了吗") conn2.close()
参考博客:www.cnblogs.com/Eva-J/articles/8253547.html
管道会产生进程安全问题,所以一般需要加锁
进程之间的数据共享
from multiprocessing import Manager
m = Manager()
dic = m,dict({'count',100}) 这样dic设定为共享的字典
由于进程之间抢占资源会引起进程之间不安全,需要枷锁 from multiprocessing import Manager,Process,Lock def main(dic,lock): lock.acquire() dic['count'] -= 1 lock.release() if __name__ == '__main__': m = Manager() l = Lock() dic = m.dict({'count':100}) #共享 p_lst = [] for i in range(20): #起20个进程 p = Process(target=main,args=(dic,l)) p.start() p_lst.append(p) for i in p_lst: i.join() print("主进程%s"%dic)
进程池:
每次开启进程,都会创建一个属于这个进程的内存空间
进程之间的切换,操作系统调度,都比较耗性能
所以需要设计一个进程池,这个池子指定能存放多少个进程,先将这些进程创建好
任务去进程池中找一个进程进行处理,处理后任务把该进程放回池中,用于下一个任务
注意与信号量的区别:
信号量是同时只能有5个进程运行,但是环视会创建于任务相对的进程
,而进程池就只会创建5个进程,去运行所有的任务
更高级的进程池:
至少有3个进程,最多有20个进程,它会有两个值,一个上限一个下限
如,在不同的时间段,会有不同的请求的波动,所以他会根据请求量,的增多会加一个进程
至到加到自己设定的最大进程值,当比较空闲的时候,进程数会减到最小
python中没有这种高级的进程池
# p.map(funcname,iterable) 默认异步的执行任务,且自带close和join
# p.apply 同步调用的
# p.apply_async 异步调用 和主进程完全异步 需要手动close 和 join配合
p.close() 接受进程池接受任务
p.join() #感知进程池中的任务结束
from multiprocessing import Pool def func(n): for i in range(10): print(n+1) pool = Pool(5) 起个5个进程池 pool.map(func,range(100)) #100个任务
#进程与进程池的对比


from multiprocessing import Process,Pool import time def func(n): for i in range(10): n + 1 if __name__ == '__main__': start = time.time() pool = Pool(5) pool.map(func,range(100)) t1 = time.time() - start start1 = time.time() p_lst = [] for i in range(100): p = Process(target=func,args=(i,)) p_lst.append(p) p.start() for p in p_lst: p.join() t2 = time.time() - start1 print(t1,t2)
p.apply_async ()


import os import time from multiprocessing import Pool def func(n): print('start fun%s'%n,os.getpid()) time.sleep(1) print('end func%s'%n,os.getpid()) if __name__ == '__main__': p = Pool(5) for i in range(10): p.apply_async(func,args=(i,)) p.close() p.join()
进程池实现的socket异步通信


import socket from multiprocessing import Pool def func(conn): conn.send(b'hello') print(conn.recv(1024).decode('utf-8')) conn.close() if __name__ == '__main__': p = Pool(5) sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() while True: conn, addr = sk.accept() p.apply_async(func,args=(conn,)) sk.close()


import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) ret = sk.recv(1024).decode('utf-8') print(ret) msg = input('>>>').encode('utf-8') sk.send(msg) sk.close()
return 返回值
map()
# import time # from multiprocessing import Pool # def func(i): # time.sleep(0.5) # return i*i # # if __name__ == '__main__': # p = Pool(5) # ret = p.map(func,range(100)) # print(ret)
apply_asyn
# import time # from multiprocessing import Pool # def func(i): # time.sleep(0.5) # return i*i # # if __name__ == '__main__': # p = Pool(5) # res_l = [] # for i in range(10): # res = p.apply_async(func,args=(i,)) # apply的结果就是func的返回值 # res_l.append(res) # for res in res_l:print(res.get())# 等着 func的计算结果
apply 同步
# from multiprocessing import Pool # def func(i): # return i*i # # if __name__ == '__main__': # p = Pool(5) # for i in range(10): # res = p.apply(func,args=(i,)) # apply的结果就是func的返回值 # print(res)
进程池的回调函数:,callback
import os from multiprocessing import Pool def func1(n): print('in func1',os.getpid()) return n*n def func2(nn): print('in func2',os.getpid()) print(nn) if __name__ == '__main__': print('主进程 :',os.getpid()) p = Pool(5) for i in range(10): p.apply_async(func1,args=(10,),callback=func2) #回调func2 #先执行func1 把返回值作为func2 的参数,回调函数不能给传参数。 p.close() p.join()