今日内容概要
- 创建进程的多种方式
- join方法
- 进程间数据默认隔离
- 进程间通信(IPC机制)
- 生产者消费者模型
- 进程相关方法
- 守护进程
- 僵尸进城与孤儿进程
- 互斥锁
创建进程的多种方式
1.创建进程的本质
在内存中申请一块内存空间用于运行相应的程序代码。
2.创建进程的方式
鼠标双击桌面一个应用,启动一个应用,就是会启动和创建一些进程。
3.代码创建进程
在不同的操作系统创建进程的要求不一样:
- 在windows中创建进程是以导模块的方式进行,所以创建进程的代码必须写在__main__子代码中,否则会直接报错,因为在无限制创建进程(进入死循环)
- 在linux和mac中创建进程是直接拷贝一份源代码然后执行,不要写在__main__子代码中。
# 第一种创建进程的方式 import time from multiprocessing import Process # 创建一个函数 def task(name): print('%s is running' % name) time.sleep(3) print('%s is over' % name) if __name__ == 'main': # 创建一个进程对象 p = Process(target=task,args=('kk',)) # 告诉操作系统创建一个进程 p.start() print('主进程') # 第二种创建进程的方式 from mutiprocessing import Process import time # 创建一个类继承Process父类,来使用其中的方法 class Myprocess(Process): def __inti__(self,name): super().__init__() self.name = name def run(self): print(f'{self.name}正在运行') time.sleep(3) print(f'{self.name}运行结束') if __name__ == 'main': # 创建一个进程对象 obj = Myprocess('kk') # 告诉操作系统创建了一个进程 obj.start() print('主进程')
join方法
1.概念:
主进程等待子进程结束之后在运行
2.推导
- 直接在主进程代码中添加time.sleep()让主进程延时,至子进程运行结束;
不合理,因为无法准确地把握子进程的执行时间,- 利用join方法
3.代码实操
import time from muliprocessing import Process def task(name,n): print(f'{name}正在运行') time.sleep(n) print(f'{name}运行结束') if __name__ == 'main': # 创建一个进程对象 p1 = Process(target = task,args = ('kk',3)) p2 = Process(target = task,args=('jj',2)) t1 = time.time() # 创建一个进程 p1.satrt() # 这里 通过join方法,将两个子进程一个个运行 p1.join() p2.start() # 等子进程运行完,在继续运行主进程 p2.join() end_time = time.time() - t1 print(f'程序运行时间'{end_time}) print('主进程')
进程间数据默认隔离
多个进程数据彼此之间默认是相互隔离的
- 如果想要交互,需要借助于管道队列。
# 父进程与子进程完全是两个空间,可以看成是平行世界,子进程不管怎么改都不影响父进程这边的代码 from multiprocessing import Process money = 100 def task(): dlobal money money = 666 print(f'子进程{money}$') if __name__ == '__main__': p1 = Process(target=task) p1.start() p1.join() print(f'父进程有{money}$')
进程间通信(IPC机制)
1.队列与栈
队列:先进后出(类似于排队)
栈:先进后出(类似于子弹装进弹夹)
2.代码展示
from multiprocessing imort Queue # 先创建队列列表 q = Queue(3) # 括号内参数为可容纳的数据个数,默认为2147483647 # 往队列添加数据 q.put(111) # 判断队列是否已经存满 print(q.full()) q.put(222) q.put(333) print(q.full()) # 超出数据存放极限,那么程序一直处于阻塞态,知道队列中有数据被取出 # 1.put(444) # 从队列中获取数据 print(q.get()) # 如果取不到会进入阻塞态 q.put(444) print(q.get()) print(q.get_nowait()) #如果 被取完了 会直接报错 # print(q.get_nowait()) #如果队列中 之后没有数据可取 俺么会直接报错 # 判断队列是哦福已经空了 print(q.empty())
q.full() 判断队列内是否存满,可以刚判断完里面的数据就被改动了,下面同理
q.empty()
q.get_nowait()
上述方法在多进程下不能准确使用
3.IPC机制
主进程与子进程通信
from mutiprocessing import Queue,Proces def procedure(q): q.put('子进程procedure往队列中添加的数据') def consumer(q): print('子进程的consumer 从队列中获取数据'q.get()) if __name__ == '__main__': # 在主进程中 产生q对象 确保所有的子进程使用的是相同的q q = Queue() p1 = Process(target=procedure,args=(q,)) p2 = Process(target=consumer,args=(q,)) p1.start() p2.start() print('主进程') # print('主进程 从队列中获取数据',q.get()) # 通过将 q对象创建在 主程序中, 那么子程序在产生时都会 经过q对象
生产者消费者模型
1.生产者
产生数据
2.消费者
处理数据
3.完整的生产者消费者模型至少有三个部分
生产者,消息队列,消费者
4.举栗子
爬取红牛分公司地址:
- 生产者:获取的网页数据的代码(函数)
消费者:从网页数据中筛选出符合条件的数据(函数)
进程相关方法
1.查看进程号
# 通过 current_process: from multiprocessing import current_process print (current_process().pid) # 查看当前进程号 # 通过os模块 import os print(os.getpid()) # 查看当前进程号 print(os.getppid()) # 查看它的父进程 进程号 即主进程号
2.销毁子进程
p1.terminate()
3.判断进程是否存货
# 我们都是跟操作系统打交道,都是异步的,所以代码运行速度很快,操作系统没有反应那么快 p1.is_alive
守护进程
1.如何理解守护进程
伴随着守护对象的存活儿存活,死亡而死亡from multiprocessing import Process import time def task(name): print('大内总管:%s存货'% name) time.sleep(3) print('大内总管 %s 挂了'% name) if __name__ == '__main__': p = Process(target=task,args=('kk',)) # 将子进程设置为守护进程:主进程代码结束,子进程立刻结束 p.deamon = True p.start() print('主进程')
僵尸进程与孤儿进程
1.僵尸进程
进程已经运行结束了,但是相关的资源并没有完全清空;
需要父进程参与回收。
2.孤儿进程
父进程意外死亡,子进程正常运行,该子进程就称之为孤儿进程;
孤儿进程也不是没有人管,操作系统会自动分配福利院接收。
互斥锁
模拟抢票
查票;买票from multiprocessing import Process import time import json import random # 查票 def search(name): with open(r'data.json', 'r', encoding='utf')as data_r: data = json.load(data_r) print(f'{name}正在查票 当前余票{data.get("ticket_num")}') # 买票 def buy(name): # 再次确认票 with open(r'data.json', 'r', encoding='utf')as data_r: data = json.load(data_r) # 模拟网络延迟 time.sleep(random.randint(1, 3)) if data.get('ticket_num') > 0: data['ticket_num'] -= 1 with open(r'data.json', 'w', encoding='utf')as data_w: json.dump(data, data_w) print('%s 买票成功' % name) else: print('%s 很倒霉 没有轮到票' % name) def run(name): search(name) buy(name) if __name__ == '__main__': for i in range(20): p = Process(target=run,args=('用户%s'%i,)) p.start()