很多人都会写一个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这个参数,可以根据不同的窗口宽度进行调整
网友评论