进程池实现
- 必要性
【1】 进程的创建和销毁过程消耗的资源较多
【2】 当任务量众多,每个任务在很短时间内完成时,需要频繁的创建和销毁进程。此时对计算
机压力较大
【3】 进程池技术很好的解决了以上问题。 - 原理
创建一定数量的进程来处理事件,事件处理完进程不退出而是继续处理其他事件,直到所有事件
全都处理完毕统一销毁。增加了进程的重复利用,降低了资源消耗。 - 进程池实现
【1】 创建进程池对象,放入适当的进程
from multiprocessing import Pool
Pool(processes)
功能: 创建进程池对象
参数: 指定进程数量,默认根据系统自动判定
【2】 将事件加入进程池队列执行
pool.apply_async(func,args,kwds)
功能: 使用进程池执行 func事件
参数: func 事件函数
args 元组 给func按位置传参
kwds 字典 给func按照键值传参
返回值: 返回函数事件对象
【3】 关闭进程池
pool.close()
功能: 关闭进程池
【4】 回收进程池中进程
pool.join()
功能: 回收进程池中进程
"""
进程池使用演示
"""
from multiprocessing import Pool
from time import sleep,ctime
# 进程池事件函数
def worker(msg):
sleep(2)
print(ctime(),'--',msg)
return 8888
# 创建进程池
pool = Pool(4)
# 向进程池中添加事件
for i in range(10):
msg = "Tedu %d"%i
r = pool.apply_async(func=worker,
args=(msg,))
# 关闭进程池
pool.close()
# 回收进程池
pool.join()
print(r.get()) # 获取进程池事件函数返回值
练习:
"""
使用进程池去备份一个目录,该目录中包含若干个普通文件。
提示: os.listdir()
os.path.getsize()
os.mkdir() 创建一个目录
* 至少同时拷贝4个文件,并且仅能创建4个进程
拷贝过程中实时打印拷贝的百分比
"""
from multiprocessing import Pool,Queue
import os
q = Queue() # 消息队列
# 拷贝一个文件,作为进程池事件
# 拷贝啥,从哪拷,拷到哪?
def copy_file(file,old_dir,new_dir):
fr = open(old_dir+'/'+file,'rb')
fw = open(new_dir+'/'+file,'wb')
while True:
data = fr.read(1024 * 10)
if not data:
break
n = fw.write(data)
q.put(n) # 字节数传入消息队列
fr.close()
fw.close()
def main():
"""
创建进程池,调用拷贝文件的函数作为事件
"""
base_path = "/home/tarena/" #基准目录
dir = input("Dir:") #要备份的目录
old_dir = base_path + dir # 要备份目录路径
new_dir = old_dir+'-备份' # 拷到这
os.mkdir(new_dir)
file_list = os.listdir(old_dir) #拷这些
# 获取目录的总大小
total_size = 0
for i in file_list:
total_size += os.path.getsize(old_dir+'/'+i)
# 创建进程池
pool = Pool(4)
for file in file_list:
pool.apply_async(copy_file,
args=(file,old_dir,new_dir))
pool.close()
print("目录大小:%.2fM"%(total_size/1024/1024))
copy_size = 0 # 已经拷贝了的大小
while copy_size < total_size:
copy_size += q.get()
print("拷贝了%.1f%%"%(copy_size/total_size*100))
pool.join()
if __name__ == '__main__':
main()