网络编程-进程-5、通过多进程实现多任务下载文件
知识点:我们要实现多进程去下载一个文件下的几十个文件,如果按照之前说的有几个任务就创建几个进程,那么我下在几万个文件,那么就要创建几万个进程?显然是不可能的,系统根本承受不了,所以这里要用到进程里面的另外一个方式-进程池。
进程池:就是创建一个进程池,我把要执行的任务放进进程池,但是进程池存放任务的数量是自己手动设置的,假如一次最多放五个任务,那么这个五个运行完,再放五个进来运行,这样运行的进程数是固定的,能循环运行成千上万个进程任务
1、以下载器代码为例,使用到的知识点:进程池,队列:
#!/usr/bin/env python # coding=utf-8 # author:刘仲 # datetime:2018/7/26 9:23 # software: PyCharm from multiprocessing import Pool import multiprocessing import os,time def copy_file(q,filename, old_file_name, new_file_name): old_file = open(old_file_name+'/' + filename, 'rb') # 读取原文件里的内容 data1 = old_file.read() old_file.close() new_file = open(new_file_name+'/' + filename, 'wb') # 将原文件的内容写到新文件里 new_file.write(data1) new_file.close() time.sleep(0.2) q.put(filename) def main(): # 用户输入要拷贝的文件夹名字 old_file_name = input('请输入要拷贝的文件夹名字:') # 创建一个新的文件夹 new_file_name = old_file_name + '[复制]' try: os.mkdir(new_file_name) except: print('文件已存在') # 创建进程池 po = Pool(5) # 将拷贝文件夹下的文件的任务一个个放到进程池 q = multiprocessing.Manager().Queue() # 进程池里创建队列对象要用这种方式,此处采用队列是为了制作下载进度显示 # 保持子进程与主进程之间的通信,为了统计子进程下载一个文件,主进程获取一个来统计下载进度 list = os.listdir('./test') for filename in list: po.apply_async(copy_file, args=(q, filename, old_file_name, new_file_name)) # 关闭进程池 po.close() # 等待子进程结束 # po.join() # 标记初始下载数量 flag =0 while True: q.get() # 获取队列里消息 # print('已下载文件:%s' % num) flag += 1 print('\r下载进度:%.2f' % (flag*100/len(list)),end='') # \r回到开始行输出,保证了只显示一个结果 if flag >= len(os.listdir('./test')): # 如果下载数量大于或等于原文件中的数量,就退出循环 break if __name__ == '__main__': main()
运行效果如下: