Cool_Breeze 发表于 2020-8-6 21:28:42

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

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

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


# 先就这样吧

'''
@ BY Cool_Breeze
@ Rev 03
@ 2020/08/10
'''


#coding=utf-8

import shutil
import os
import time
from multiprocessing import Process,Pool,Queue,Manager
from threading import Thread
from concurrent.futures import ThreadPoolExecutor


class copyf_show:
    '''
    # 多进程复制文件
    # 多进程复制文件加显示进度
    # despath 目标目录
    # soupath 源目录
    '''
    def __init__(self, despath, soupath):
      self.d = despath
      self.s = soupath
      self.st = os.path.dirname(soupath)
      self.q = Manager().Queue()
      self.show_d = {} #show
      self.count = 0 #show
      self.total = 0 #show
      if not os.path.isdir(self.d): os.mkdir(self.d)

    def pro_pool(self):
      '''
      # 实时复制文件
      # 先启动扫描目录,向管道发送数据
      # 开启进程池,等待管道接受数据
      # 一个进程复制一个目录层文件
      '''
      print('正在从 {} 复制所有文件到 {}'.format(self.s, self.d))
      time_node = time.time()
      count = 0
      ps = Process(target=self.scanfile)
      ps.start()
      p = Pool() #进程数量
      while True:
            if self.q.empty(): continue
            t = self.q.get()
            if not t: break
            count += len(list(t.values()))
            p.apply_async(self.pro_cp, (t,))
      ps.join()
      p.close()
      p.join()
      print('总计文件数量:{}\n耗时:{} 秒'.format(count,round(time.time() - time_node, 2)))

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

    def pro_cp(self, dif):
      '''
      # 判断目标目录是否存在
      # 切换路径,复制文件
      '''
      dpa = list(dif.keys()).replace(self.st, self.d)
      if not os.path.isdir(dpa): os.mkdir(dpa)
      os.chdir(dpa)
      for i,j in dif.items():
            for nn in :
                shutil.copy(nn, dpa)
      
    def show_fun(self):
      '''
      # 开启线程城池复制文件并打印进度条
      '''
      print('正在从 {} 复制所有文件到 {}'.format(self.s, self.d))
      self.show_scanfile()
      self.count = 0
      print('总计文件数量:{}'.format(self.total))
      pp = Thread(target=self.show_pgr)
      pp.setDaemon(True)# 主程序退出结束
      pp.start()
      for d,f in self.show_d.items():
            self.show_pool(d, f)
      pp.join()

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

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

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

    def show_cp(self, file):
      '''
      # 绝对路径
      # 复制文件file = (src, dst)
      '''
      shutil.copy(file, file)


if __name__ == '__main__':
    path = r'D:\GIN\py\pool_copy_file\t'
    soup = r'D:\GIN\py\photo\photo'
    t = copyf_show(path, soup)
    t.pro_pool()
    t.show_fun()
    print('Done!')

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

请按任意键继续. . .

Cool_Breeze 发表于 2020-8-10 22:36:39

正在从 C:\user\穿越火线 复制所有文件到 D:\腾讯游戏
总计文件数量:14372
**************************************************************************************************** 100%
耗时:239.89 秒
正在从 C:\user\英雄联盟 复制所有文件到 D:\腾讯游戏
总计文件数量:39048
***************                                                                                    15%

hrp 发表于 2020-8-11 00:36:19

这个厉害了,但是看你的变量名简写真的太难受了哈哈哈{:10_250:}{:10_250:}{:10_250:}

Cool_Breeze 发表于 2020-8-11 08:06:22

hrp 发表于 2020-8-11 00:36
这个厉害了,但是看你的变量名简写真的太难受了哈哈哈

哈哈,复制大量小文件还不错!那个错误处理没有写!
页: [1]
查看完整版本: python3 多进程复制文件,多线程复制文件加显示进度条(持续更新)Rev03