创建进程的多种方式
1.创建进程方式一
from multiprocessing import Process
import time
# 创建进程方式一
def task(name):
print(f'子进程{name}开始运行') # 2 子进程lili开始运行
time.sleep(3)
print(f'子进程{name}运行结束') # 3 子进程ili运行结束
if __name__ == '__main__':
# 创建进程
p = Process(target=task, args=('lili',))
p.start()
print('主进程') # 1 主进程
2.创建进程方式二
# 创建进程方式二
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print(f'子进程{self.name}运行开始') # 2 子进程lili开始运行
time.sleep(3)
print(f'子进程{self.name}运行结束') # 3 子进程ili运行结束
if __name__ == '__main__':
obj = MyProcess('lili')
obj.start()
print('主进程') # 1 主进程
join方法
1.join方法作用:使子进程运行完毕后再执行注进程
from multiprocessing import Process
import time
def task(name):
print(f'子进程{name}开始运行') # 1 子进程lili开始运行
time.sleep(3)
print(f'子进程{name}运行结束') # 2 子进程lili运行结束
if __name__ == '__main__':
# 创建进程
p = Process(target=task, args=('lili',))
p.start() # 创建子进程
p.join() # 子进程运行完毕后执行主进程
print('主进程') # 3 主进程

2.多进程中join方法位置不同子进程运行结果不同
方式一:
from multiprocessing import Process
import time
def task(name):
print(f'子进程{name}运行开始') # 1 子进程lili运行开始 # 3 子进程xixi运行开始
time.sleep(4)
print(f'子进程{name}运行结束') # 2 子进程lili运行结束 # 4子进程xixi运行结束
if __name__ == '__main__':
p = Process(target=task, args=('lili',))
p1 = Process(target=task, args=('xixi',))
p.start()
p.join()
p1.start()
p1.join()
print('主进程') # 5 主进程

方式二:
from multiprocessing import Process
import time
def task(name):
print(f'子进程{name}运行开始') # 1 子进程lili运行开始 # 2子进程xixi运行开始
time.sleep(4)
print(f'子进程{name}运行结束') # 4 子进程lili运行结束 # 3子进程xixi运行结束
if __name__ == '__main__':
p = Process(target=task, args=('lili',))
p1 = Process(target=task, args=('xixi',))
p.start()
p1.start()
p.join()
p1.join()
print('主进程') # 5 主进程

进程间数据隔离
进程之间的数据是默认隔离的,如果需要数据交互需要通过'管道'或者'队列'
from multiprocessing import Process
age = 18
def task():
global age # 因为进程之间数据是隔离的所以子进程无法更改主进程的数据
age = 22
print(f'子进程:{age}') # 子进程:22
if __name__ == '__main__':
p = Process(target=task)
p.start()
p.join()
print(f'主进程:{age}') # 主进程:18
进程间通信(IPC机制)
1.数据存放与取出-q.put(1)、q.get()
超出数据存放极限 那么程序一致处于阻塞态 直到队列中有数据被取出
超出数据存放极限 那么程序一致处于阻塞态 直到队列中有数据被放入
2.数据取出(没有数据直接报错)-q.get_nowait()
3.判断数据是否存满与取完-q.full()、q.empty()
False 判断数据未存放满与未取完
True 判断数据已存放满与取完
队列:先进先出法 消息队列:进程之间数据的存放与获取
from multiprocessing import Process, Queue
# 创建队列对象
q = Queue(3) # 存放数据的个数,默认:SEM_VALUE_MAX = 2147483647
# 添加数据
q.put(1)
q.put(2)
print(q.full()) # False 判断数据是否存放满
q.put(3)
print(q.full()) # True 判断数据是否存放满
# q.put(4) # 超出数据存放极限 那么程序一致处于阻塞态 直到队列中有数据被取出
print(q.get_nowait()) # 1
print(q.get_nowait()) # 2
print(q.get_nowait()) # 3
print(q.get_nowait()) # 没有数据取直接报错
print(q.get()) # 1
print(q.empty()) # False 判断数据是否取完
print(q.get()) # 2
print(q.get()) # 3
print(q.empty()) # True 判断数据是否取完
# print(q.get()) # 超出数据存放极限 那么程序一致处于阻塞态 直到队列中有数据被放入
4.针对多进程失效
5.主进程与子进程通信、子进程与子进程通信
主进程与子进程通信:
from multiprocessing import Process, Queue
def task(q):
q.put('子进程放入队列的数据')
if __name__ == '__main__':
q = Queue()
p = Process(target=task, args=(q,))
p.start()
print('主进程取得队列中', q.get()) # 主进程取得队列中 子进程放入的数据
子进程与子进程通信:
def task(q):
q.put('子进程task放入队列的数据')
def task1(q):
print('子进程task1取得队列中', q.get()) # 子进程task1取得队列中 子进程task放入队列的数据
if __name__ == '__main__':
q = Queue()
p = Process(target=task, args=(q,))
p1 = Process(target=task1, args=(q,))
p.start()
p1.start()
print('主进程')
生产者消费者模型
1.生产者:产生数据
2.消费者:处理数据
3.生产者与消费者的组成部分:生产者、消息队列/数据库、消费者
进程对象相关方法
1.查看进程号
查看子进程号-current_process().pid、os.getpid()
查看父进程号-os.getppid()
2.删除子进程-p.terminate()
from multiprocessing import Process, Queue, current_process
import os
def task(q):
q.put('子进程放入队列的数据')
print('子进程进程号:', current_process().pid) # 子进程进程号: 12100
print('子进程进程号:', os.getpid()) # 子进程进程号: 12100
print('父进程进程号:', os.getppid()) # 父进程进程号: 14388
if __name__ == '__main__':
q = Queue()
p = Process(target=task, args=(q,))
# p.terminate() # 终止子进程p
p.start()
print('主进程取得队列中', q.get()) # 主进程取得队列中 子进程放入的数据
print('主进程进程号:', current_process().pid) # 主进程进程号: 14388
print('主进程进程号:', os.getpid()) # 主进程进程号: 14388
print('父进程进程号:', os.getppid()) # 父进程进程号: 4644
守护进程
在创建子进程之前就设置为守护进程,主程序结束子程序立马结束
from multiprocessing import Process
import time
def task(name):
print(f'子进程{name}存活') # 1 子进程lili存活
time.sleep(3)
print(f'子程序{name}死亡')
if __name__ == '__main__':
# 创建进程
p = Process(target=task, args=('lili',))
p.daemon = True # 在创建子进程之前就设置为守护进程,主程序结束子程序立马结束
p.start()
# p.daemon = True
# p.join() # 必须设置在子进程创建之前
time.sleep(2)
print('主进程死亡') # 2 主进程死亡
僵尸进程与孤儿进程
1.僵尸进程:子进程已结束,子进程还有数据需要父进程清理
2.孤儿进程:父进程突然死亡,子进程的数据只能由系统中的'福利院'清理
互斥锁
模拟抢票系统:
from multiprocessing import Process, Lock
import json
import time
import random
# 查询票数
def check_tickets(name):
# 打开文件
with open('ticket', 'r', encoding='utf8') as f:
data = json.load(f)
print(f"{name}查看剩余票数{data.get('number_of_train_tickets')}")
# 抢票
def ticket_grabbing(name):
# 查票
with open('ticket', 'r', encoding='utf8') as f:
data = json.load(f)
# 网络延迟
time.sleep(random.randint(1, 5))
# 判断是否有票
if data.get('number_of_train_tickets') > 0:
data['number_of_train_tickets'] -= 1
# 将剩余票数写入文件中
with open('ticket', 'w', encoding='utf8') as f:
json.dump(data, f)
print(f'{name}抢票成功')
else:
print(f'{name}没票啦')
def run(lock,name):
check_tickets(name)
lock.acquire()
ticket_grabbing(name)
lock.release()
if __name__ == '__main__':
lock = Lock()
for i in range(5):
p = Process(target=run, args=(lock, f'用户{i}',))
p.start()
posted on
浙公网安备 33010602011771号