优秀答案推荐
Strategy:
战略:
Determine the length of the file first so that you can tell tqdm what it is.
Normally then you'd use shutil.copyfile (or shutil.copyfileobj) to actually copy the file but neither of those functions provide a way to receive updates during the copy, which we need to forward to tqdm:
- So I created a slightly modified version of
copyfileobj
which supports passing an update function which is called regularly during copying.
- Then I passed the tqdm's
update
method as the update function to the new copyfileobj
so that it gets called regularly during the copy.
Code:
代码:
import os
from tqdm import tqdm
def copy_with_progress(source_filepath, target_filepath):
with open(source_filepath, 'rb') as source_file:
with open(target_filepath, 'wb') as target_file:
source_file.seek(0, os.SEEK_END)
file_length = source_file.tell()
print(f'Copying: {source_filepath} ({file_length:n} bytes)')
source_file.seek(0, os.SEEK_SET)
with tqdm(total=file_length, unit='B', unit_scale=True) as progress_bar:
copyfileobj_with_progress(
source_file, target_file,
progress_func=progress_bar.update)
# Based on shutil.copyfileobj
_WINDOWS = os.name == 'nt'
COPY_BUFSIZE = 1024 * 1024 if _WINDOWS else 64 * 1024
def copyfileobj_with_progress(fsrc, fdst, length=0, progress_func=None):
if not length:
length = COPY_BUFSIZE
if progress_func is None:
progress_func = lambda offset: None
# Localize variable access to minimize overhead.
fsrc_read = fsrc.read
fdst_write = fdst.write
while True:
buf = fsrc_read(length)
if not buf:
break
fdst_write(buf)
progress_func(len(buf)) # delta offset
更多回答
You could also directly retrieve the size with os.stat()
, without needing to seek back and forth.
您还可以使用os.stat()直接检索大小,而不需要来回查找。
BTW, you might think about trying to correctly handle file-like objects that aren't seekable (which will be pretty much identical to the set for which stat won't give you a useful size -- FIFOs, many kinds of character devices, files in procfs, etc). Even if that just means falling back to a normal copy without a progress bar, it's better to gracefully degrade than fail outright.
顺便说一句,您可能会考虑尝试正确地处理不可查找的类似文件的对象(这将与stat不会为您提供有用大小的集合基本相同--FIFO、多种字符设备、prof中的文件等)。即使这只是意味着退回到没有进度条的正常副本,但优雅地降级也比彻底失败要好。
我是一名优秀的程序员,十分优秀!