美文网首页
Python带有进度条的文件复制

Python带有进度条的文件复制

作者: 三药 | 来源:发表于2018-05-01 20:42 被阅读0次

很多人都会写一个python文件复制的代码,也知道如何利用tqdm模块来显示进度条,但是让文件复制有进度条的代码呢?我在网上搜索过好像大多数都很复杂,时间也比较早,所以研究了一下。
tqdm的模块关键在于如何传入它的第一个迭代器函数,最开始我尝试用.readlines()导入到tqdm中:

import tqdm
source = r'A:\source.txt'
target = r'A:\target.txt'
with open(source,'rb') as s:
    with open(target,'wb') as t:
        for line in tqdm.tqdm(s.readlines()):
            t.write(line)
image.png

但是该方法只是在复制文档的时候用的挺好,它迭代的最小单位是基于文件的二进制行数,直到复制一个大文件的时候,我才发现它的速度巨慢。
然后在《Python Cookbook》的文件和I/O章节,发现可以用iter()和functools.partial()来对固定大小的数据块进行迭代,网上的资料可以点击这里

from functools import partial

RECORD_SIZE = 32

with open('somefile.data', 'rb') as f:
    records = iter(partial(f.read, RECORD_SIZE), b'')
    for r in records:
        ...

将数据块定位1兆(1048576B)后,进度条代码可以优化如下:

with open(sourceFile, 'rb') as s:
    with open(targetFile, 'wb') as fd:
        record_size = 1048576
        records = iter(partial(s.read, record_size), b'')
        size = int(os.path.getsize(os.path.abspath(sourceFile))/record_size)
        for data in tqdm.tqdm(records,total=size,unit='MB',
                                desc = sourceFile,mininterval=1,ncols=80,):
            fd.write(data)

关于tqdm的关键字参数,可以参考tqdm的文档
和网上其他人的教程,如这篇

然后关于文件夹复制的代码,就是一个简单的递归,并且我也将其加入了tqdm模块,这样也可以显示文件夹的复制进度。
最后,在复制文件过程中,使用了一个while循环来检查文件的MD5码,直到目标文件和源文件MD5相等,或者检查次数用尽,最后得出的代码如下:

import os
import tqdm
from hashlib import md5
from functools import partial

def copy_dir(sourceDir,  targetDir):
    if sourceDir.find(".svn") > 0:
        return
    for file in tqdm.tqdm(os.listdir(sourceDir),unit='files',desc = sourceDir):
        sourceFile = os.path.join(sourceDir,  file)
        targetFile = os.path.join(targetDir,  file)
        if os.path.isfile(sourceFile):
            if not os.path.exists(targetDir):
                os.makedirs(targetDir)
            if not  os.path.exists(targetFile) or(
                    os.path.exists(targetFile) and (
                    os.path.getsize(targetFile) !=
                    os.path.getsize(sourceFile))):

                g_s = open(sourceFile, 'rb')
                g = g_s.read()
                md5_source = md5(g).hexdigest()
                md5_target = None
                g_s.close()
                checking_time = 5
                while not (md5_source == md5_target and checking_time > 0):
                    with open(sourceFile, 'rb') as s:
                        with open(targetFile, 'wb') as fd:
                            record_size = 1048576
                            records = iter(partial(s.read, record_size), b'')
                            size = int(os.path.getsize(os.path.abspath(sourceFile))/record_size)
                            for data in tqdm.tqdm(records,
                                                  total=size,
                                                  unit='MB',
                                                  desc = sourceFile,
                                                  mininterval=1,
                                                  ncols=80,):
                                fd.write(data)
                    with open(targetFile, 'rb') as h_s:
                        h =h_s.read()
                        md5_target = md5(h).hexdigest()
                    checking_time -=1
        if os.path.isdir(sourceFile):
            First_Directory = False
            copy_dir(sourceFile, targetFile)

在终端中显示效果如下:


image.png
image.png

大家可以通过查阅tqdm的文档,来修改tqdm的参数,以达到调整显示效果的目的,例如:ncols=80这个参数,可以根据不同的窗口宽度进行调整

相关文章

网友评论

      本文标题:Python带有进度条的文件复制

      本文链接:https://www.haomeiwen.com/subject/xxsfrftx.html