鱼C论坛

 找回密码
 立即注册
查看: 3038|回复: 3

[作品展示] python3 多进程复制文件,多线程复制文件加显示进度条(持续更新)Rev03

[复制链接]
发表于 2020-8-6 21:28:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 Cool_Breeze 于 2020-8-10 11:28 编辑

##############
# 还没有写完
# 欢迎大佬指点
##############


# 先就这样吧

  1. '''
  2. @ BY Cool_Breeze
  3. @ Rev 03
  4. @ 2020/08/10
  5. '''


  6. #coding=utf-8

  7. import shutil
  8. import os
  9. import time
  10. from multiprocessing import Process,Pool,Queue,Manager
  11. from threading import Thread
  12. from concurrent.futures import ThreadPoolExecutor


  13. class copyf_show:
  14.     '''
  15.     # 多进程复制文件
  16.     # 多进程复制文件加显示进度
  17.     # despath 目标目录
  18.     # soupath 源目录
  19.     '''
  20.     def __init__(self, despath, soupath):
  21.         self.d = despath
  22.         self.s = soupath
  23.         self.st = os.path.dirname(soupath)
  24.         self.q = Manager().Queue()
  25.         self.show_d = {} #show
  26.         self.count = 0 #show
  27.         self.total = 0 #show
  28.         if not os.path.isdir(self.d): os.mkdir(self.d)

  29.     def pro_pool(self):
  30.         '''
  31.         # 实时复制文件
  32.         # 先启动扫描目录,向管道发送数据
  33.         # 开启进程池,等待管道接受数据
  34.         # 一个进程复制一个目录层文件
  35.         '''
  36.         print('正在从 {} 复制所有文件到 {}'.format(self.s, self.d))
  37.         time_node = time.time()
  38.         count = 0
  39.         ps = Process(target=self.scanfile)
  40.         ps.start()
  41.         p = Pool() #进程数量
  42.         while True:
  43.             if self.q.empty(): continue
  44.             t = self.q.get()
  45.             if not t: break
  46.             count += len(list(t.values())[0])
  47.             p.apply_async(self.pro_cp, (t,))
  48.         ps.join()
  49.         p.close()
  50.         p.join()
  51.         print('总计文件数量:{}\n耗时:{} 秒'.format(count,round(time.time() - time_node, 2)))

  52.     def scanfile(self):
  53.         '''
  54.         # 扫描一层目录,生成字典
  55.         # 绝对路径为key,文件列表为值
  56.         # 向管道发送字典
  57.         '''
  58.         for root,dirs,files in os.walk(self.s):
  59.             self.q.put({root:files})
  60.         self.q.put(False)

  61.     def pro_cp(self, dif):
  62.         '''
  63.         # 判断目标目录是否存在
  64.         # 切换路径,复制文件
  65.         '''
  66.         dpa = list(dif.keys())[0].replace(self.st, self.d)
  67.         if not os.path.isdir(dpa): os.mkdir(dpa)
  68.         os.chdir(dpa)
  69.         for i,j in dif.items():
  70.             for nn in [os.path.join(i,k) for k in j]:
  71.                 shutil.copy(nn, dpa)
  72.         
  73.     def show_fun(self):
  74.         '''
  75.         # 开启线程城池复制文件并打印进度条
  76.         '''
  77.         print('正在从 {} 复制所有文件到 {}'.format(self.s, self.d))
  78.         self.show_scanfile()
  79.         self.count = 0
  80.         print('总计文件数量:{}'.format(self.total))
  81.         pp = Thread(target=self.show_pgr)
  82.         pp.setDaemon(True)# 主程序退出结束
  83.         pp.start()
  84.         for d,f in self.show_d.items():
  85.             self.show_pool(d, f)
  86.         pp.join()

  87.     def show_pgr(self):
  88.         '''
  89.         # 进度条
  90.         # 已复制数除以总数乘以100
  91.         # 计时
  92.         '''
  93.         time_node = time.time()
  94.         while True:
  95.             cls = round(self.count/self.total*100)
  96.             print('\r{:<100} {}%'.format('*'*cls, cls),end='')
  97.             if cls == 100:
  98.                 print('\n耗时:{} 秒'.format(round((time.time() - time_node), 2)))
  99.                 break
  100.             time.sleep(0.1)

  101.     def show_scanfile(self):
  102.         '''
  103.         # 扫描一层目录,生成字典
  104.         # 绝对路径为key,文件列表为值
  105.         #
  106.         '''
  107.         for root,dirs,files in os.walk(self.s):
  108.             self.total += len(files)
  109.             self.show_d.update({root:files})

  110.     def show_pool(self, root, fl):
  111.         '''
  112.         # root = 目录, fl = 文件列表
  113.         # 多线程
  114.         '''
  115.         dpa = root.replace(self.st, self.d)
  116.         if not os.path.isdir(dpa): os.mkdir(dpa)
  117.         os.chdir(dpa)
  118.         with ThreadPoolExecutor(None, self.show_cp) as p:
  119.             p.map(self.show_cp, [(root + os.sep + f, dpa) for f in fl])
  120.         p.shutdown()
  121.         self.count += len(fl)

  122.     def show_cp(self, file):
  123.         '''
  124.         # 绝对路径
  125.         # 复制文件file = (src, dst)
  126.         '''
  127.         shutil.copy(file[0], file[1])


  128. if __name__ == '__main__':
  129.     path = r'D:\GIN\py\pool_copy_file\t'
  130.     soup = r'D:\GIN\py\photo\photo'
  131.     t = copyf_show(path, soup)
  132.     t.pro_pool()
  133.     t.show_fun()
  134.     print('Done!')
复制代码


###############
测试结果:
  1. 正在从 D:\GIN\py\photo\photo 复制所有文件到 D:\GIN\py\pool_copy_file\t
  2. 总计文件数量:2296
  3. 耗时:2.82 秒
  4. 正在从 D:\GIN\py\photo\photo 复制所有文件到 D:\GIN\py\pool_copy_file\t
  5. 总计文件数量:2296
  6. **************************************************************************************************** 100%
  7. 耗时:2.91 秒
  8. Done!

  9. 请按任意键继续. . .
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-8-10 22:36:39 | 显示全部楼层
  1. 正在从 C:\user\穿越火线 复制所有文件到 D:\腾讯游戏
  2. 总计文件数量:14372
  3. **************************************************************************************************** 100%
  4. 耗时:239.89 秒
  5. 正在从 C:\user\英雄联盟 复制所有文件到 D:\腾讯游戏
  6. 总计文件数量:39048
  7. ***************                                                                                      15%
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-11 00:36:19 From FishC Mobile | 显示全部楼层
这个厉害了,但是看你的变量名简写真的太难受了哈哈哈
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-8-11 08:06:22 | 显示全部楼层
hrp 发表于 2020-8-11 00:36
这个厉害了,但是看你的变量名简写真的太难受了哈哈哈

哈哈,复制大量小文件还不错!那个错误处理没有写!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-25 10:59

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表