多进程_篇
什么是一个进程
进程是一个已运行程序的实例
程序与进程的区别
程序是一个死的,进程是一个程序运行在内存中
当创建进程时,子进程是完全复制的父进程(主进程)的
原理; 实例 (不能在Windows上运行)
实例:
# 多进程
# 实现同时执行多个方法
import os
# 任务一 跳舞
import time
def dance():
# 输出多次
for i in range(3):
print('我在跳舞!')
time.sleep(1)
# 任务二 唱歌
def sing():
# 输出多次
for i in range(3):
print('我在唱歌')
time.sleep(1)
# 创建多进程
stat = os.fork()
# 判断谁是主进程与子进程 主进程ID大于0
if stat == 0:
# 调用子进程
dance()
else:
# 调用主进程
sing()
多次fork
# coding=utf-8
import os
import time
# 注意,fork函数,只在Unix/Linux/Mac上运行,windows不可以
pid = os.fork()
if pid == 0:
print('hello 1')
else:
print('hello 2')
pid = os.fork()
if pid == 0:
print('hello 3')
else:
print('hello 4')
time.sleep(1)
使用类创建多进程 (推荐) 可跨平台运行
需要使用模块 process
实例
import os
import time
from multiprocessing import Process
# 使用类创建一个多进程
def sing():
# 查看进程id
print(f'我的进程id是:{os.getpid()}')
print(f'父进程id是:{os.getppid()}')
for i in range(3):
print('我在唱歌')
time.sleep(1)
def dance():
# 查看进程id
print(f'我的进程id是:{os.getpid()}')
print(f'父进程id是:{os.getppid()}')
for i in range(3):
print('我在跳舞')
time.sleep(1)
# 创建调试方法 (规范)
def main():
# 创建一个进程对象
p1 = Process(target=sing) # 注意: 这里调用方法是不能加括号的
# 开启进程
p1.start()
# 创建一个子进程
p2 = Process(target=dance)
# 开启进程
p2.start()
if __name__ == '__main__':
main()
运行结果:
创建了两个子进程,一个主进程
进程类参数的传递(Process)
实例:
import time
from multiprocessing import Process
# 参数传递规范 延迟:sleep 循环数:cycle
# 练习参数传递
def sing(sleep, cycle,**kwargs):
for i in range(cycle):
print('我在唱歌')
print(kwargs) # 打印关键字传参
time.sleep(sleep)
def dance(sleep, cycle):
for i in range(cycle):
print('我在跳舞')
time.sleep(sleep)
def main():
# 初始化时间
time_start = time.time()
# 创建多进程
p1 = Process(target=sing, args=(1, 3),kwargs={"kw":'sing'})
# 开启进程
p1.start()
# 创建子进程
p2 = Process(target=dance, args=(1, 3))
# 开启进程
p2.start()
# 等待子进程结束才执行
p1.join()
# 当p1结束时再执行后面的
p2.join()
print(f'运行时间:{time.time()-time_start}') # 计算运行时间
# 不管子进程是否运行结束,直接终止子进程
p1.terminate()
p2.terminate()
# 在Windows下开发 必须放在main 里面,不然会报错
if __name__ == '__main__':
main()
当子进程被主进程干掉的时候才会被回收销毁
进程池
什么是进程池?
进程池就是设定几个进程做任务,谁先干完,谁继续换活干。
例如: 公园里的小船,已知的船数量,不同的人去坐,谁先下船,就换人上船
实例:
# 进程池
import os
from multiprocessing import Pool
import time, random
def pool(i):
print('PID: {} 运行:{}'.format(os.getpid(),i))
# 随机时间
time.sleep(random.random() * 2)
p = Pool(3) # 设置进程池有三个进程
for i in range(10):
# 调用异步,分配任务
p.apply_async(pool,(i,))
p.close() # 不能在添加任务
p.join() # 等待所有子进程运行结束
print('运行结束')
进程池是解决每一个任务创建一个进程占用内存空间大的问题
进程间通信( 通过队列来实现 )
使用模块:from multiprocessing import Queue
实例:
from multiprocessing import Queue, Process
# 实例 边写边读
# 读
def read(queue):
while True:
# 读取一个
if not queue.empty():
print(queue.get())
else:
# 退出
break
# 写
def write(queue):
for i in ['a', 'b', 'c', 'd']:
# 添加进队列
queue.put(i)
def main():
# 创建一个队列
queue = Queue()
# 创建一个对象
p = Process(target=write, args=(queue,)) # 元组传入
# 启动进程
p.start()
# 创建一个对象
p1 = Process(target=read, args=(queue,)) # 元组传入
# 开启进程
p1.start()
补充:
什么是一个僵尸进程:
当子进程死的时候,主进程还在睡,迟迟没有进行对子进程的回收;子进程并没有退出,仍然占用着系统的资源
解决方法,杀死主进程,子进程由1号进程接管
什么是孤儿进程:
当主进程挂掉的时候,子进程还没运行完,此时所有的子进程由1号进程接管,当1号进程接管时,子进程将变为守护进程.
什么是守护进程:
守护进程一班用于服务;一直运行直到系统关闭,只有在任务完成后自动结束