创建进程
我们平常双击打开一个软件就相当于告诉操作系统,创造了一个进程。我们当然也可以在python代码中来创建进程
方式1:
from multiprocessing import Process
import time
def task(name):
print(f'进程{name}正在运行')
time.sleep(3)
print(f'进程{name}结束运行')
if __name__ == '__main__':
p = Process(target=task, args=('jason',))
p.start()
print('主进程结束')
打印结果如下:
方式2:
class MyProcess(Process):
def __init__(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('jason')
obj.start()
print('主进程')
'''
创建进程的代码在不同的操作系统中 底层原理是有区别的
在windows中 创建进程类似于导入模块
if __name__ == '__name__': 启动脚本
在mac、linux中 创建进程类似于直接拷贝
不需要启动脚本 但是为了兼容性 也可以使用
'''

join方法
作用:让主进程等待子进程结束之后再运行
def task(name, n):
print(f'{name}正在运行')
time.sleep(n)
print(f'{name}运行结束')
if __name__ == '__main__':
p1 = Process(target=task, args=('jason', 1))
p2 = Process(target=task, args=('kevin', 2))
p3 = Process(target=task, args=('jerry', 3))
start_time = time.time()
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
end_time = time.time() - start_time
print('总耗时:%s' % end_time)
print('主进程')
'''一定要看准join的执行位置 以及多任务情况下等待的目标'''

进程间的通信
from multiprocessing import Process
money = 100
def task():
money = 666
print(f'子进程的money:{money}')
if __name__ == '__main__':
p = Process(target=task)
p.start()
p.join()
print(f'父进程打印的money:{money}')
多个进程间的数据默认隔离,如果真的想交互,需要借助于'管道'或者'队列'
预备知识:
什么是队列:先进先出
from multiprocessing import Queue
q = Queue(3)
"""
q.full() # 判满
q.empty() # 判空
q.get_nowait() # 取值
上述方法在多进程下不能准确使用(失效)!!!
"""
IPC机制
1.主进程与子进程通信
2.子进程与子进程通信
from multiprocessing import Queue, Process
def procedure(q):
q.put('子进程procedure往队里中添加了数据')
def consumer(q):
print('子进程的consumer从队列中获取数据', q.get())
if __name__ == '__main__':
q = Queue()
p1 = Process(target=procedure, args=(q,))
p2 = Process(target=consumer, args=(q,))
p1.start()
p2.start()
print('主进程')
生产者消费者模型
生产者:产生数据(类似于我们从网站爬取数据)
消息队列/数据库
消费者:处理数据(类似于我们从爬取的数据集中筛选自己想要的数据)
进程相关方法
from multiprocessing import current_process
import os
1.查看进程号:
current_process().pid
os.getpid()
os.getppid()
2.销毁子进程
p.terminate()
3.判断进程是否存活
p.is_alive()
守护进程
如何理解守护进程:伴随守护对象的存活而存活,死亡而死亡
from multiprocessing import Process
import time
def task(name):
print(f'守护进程{name}存活')
time.sleep(2)
print(f'守护进程{name}嗝屁')
if __name__ == '__main__':
p = Process(target=task, args=('大仓',))
p.daemon = True
p.start()
print('主进程驾崩')
打印结果
没有使用join方法,所以主进程正常优先于子进程执行。由于将子进程设置为了守护进程,所以主进程一结束,子进程也立刻嗝屁,不会执行task方法
僵尸进程与孤儿进程
僵尸进程:
进程已经运行结束,但是相关的资源并没有立即完全清空,需要父进程参与回收。所有进程都会经历僵尸进程
孤儿进程:
父进程意外死亡,子进程正常运行,该子进程就称为孤儿进程
孤儿进程也不是没有人管,操作系统会自动分配'福利院'接收
模拟抢票
from multiprocessing import Process
import time
import json
import random
def search(name):
with open(r'data.json', 'r', encoding='utf8') as f:
data = json.load(f)
print('%s在查票 当前余票为:%s' % (name, data.get('ticket_num')))
def buy(name):
with open(r'data.json', 'r', encoding='utf8') as f:
data = json.load(f)
time.sleep(random.randint(1, 3))
if data.get('ticket_num') > 0:
data['ticket_num'] -= 1
with open(r'data.json', 'w', encoding='utf8') as f:
json.dump(data, f)
print('%s买票成功' % name)
else:
print('%s很倒霉 没有抢到票' % name)
def run(name):
search(name)
buy(name)
if __name__ == '__main__':
for i in range(10):
p = Process(target=run, args=('用户%s'%i, ))
p.start()