shutil.copy()没有提供任何跟踪进度的选项,不会。最多可以监视目标文件的大小(使用
os.*目标文件名上的函数)。
替代方法是实现您自己的复制功能。实现确实非常简单;
shutil.copy()基本上是一个
shutil.copyfile()加号
shutil.copymode();
shutil.copyfile()依次将实际工作委托给*(链接到Python
3.8.2源代码)。
shutil.copyfileobj()
实施自己的方法
shutil.copyfileobj()以包含进度应该是微不足道的;注入对回调函数的支持,以便在每次复制另一个块时报告通知您的程序:
import osimport shutildef copyfileobj(fsrc, fdst, callback, length=0): try: # check for optimisation opportunity if "b" in fsrc.mode and "b" in fdst.mode and fsrc.readinto: return _copyfileobj_readinto(fsrc, fdst, callback, length) except AttributeError: # one or both file objects do not support a .mode or .readinto attribute pass if not length: length = shutil.COPY_BUFSIZE fsrc_read = fsrc.read fdst_write = fdst.write copied = 0 while True: buf = fsrc_read(length) if not buf: break fdst_write(buf) copied += len(buf) callback(copied)# differs from shutil.COPY_BUFSIZE on platforms != WindowsREADINTO_BUFSIZE = 1024 * 1024def _copyfileobj_readinto(fsrc, fdst, callback, length=0): """readinto()/memoryview() based variant of copyfileobj(). *fsrc* must support readinto() method and both files must be open in binary mode. """ fsrc_readinto = fsrc.readinto fdst_write = fdst.write if not length: try: file_size = os.stat(fsrc.fileno()).st_size except OSError: file_size = READINTO_BUFSIZE length = min(file_size, READINTO_BUFSIZE) copied = 0 with memoryview(bytearray(length)) as mv: while True: n = fsrc_readinto(mv) if not n: break elif n < length: with mv[:n] as smv: fdst.write(smv) else: fdst_write(mv) copied += n callback(copied)
然后在回调中,将
copied大小与文件大小进行比较。
请注意,在上述实现中,我们寻找机会对 二进制
文件使用不同的方法,您可以在其中使用
fileobj.readinto()和
memoryview对象来避免冗余数据的复制。请参阅原始
_copyfileobj_readinto()实现以进行比较。
- …的
shutil.copyfileobj()
_脚注 _将实际工作委托给 :从Python 3.8开始,在OS X和Linux上,copyfile()
实现将文件复制委托给特定于OS的优化系统调用(分别为tofcopyfile()
和sendfile()
),但是这些调用没有钩子来跟踪进度,因此,如果您 需要 跟踪进度,则 无论如何 都要禁用这些委托路径。在Windows上,代码使用上述_copyfileobj_readinto()
功能。



