如何在Python中修改缓冲区大小提升共享盘大文件复制速度?
解决Python复制大文件到共享驱动器速度慢的问题
哥们,我之前也踩过这个坑——用shutil.copy复制大文件到网络共享盘时,速度比手动拖慢太多,核心原因就是它默认的缓冲区太小了,频繁的IO读写拖垮了效率。下面给你具体的优化方案和替代方法:
一、调整缓冲区大小,优化shutil复制效率
shutil.copy底层其实是调用了shutil.copyfileobj,而这个方法默认只用16KB的缓冲区,对付3GB的大文件完全不够看。咱们可以直接用copyfileobj手动指定更大的缓冲区,比如64MB甚至128MB(根据你的系统内存调整就行)。
修改后的代码示例:
import os import shutil def copyAllFiles(src, newPath): src_files = os.listdir(src) # 自定义缓冲区,这里设为64MB,你可以按需调整 BUFFER_SIZE = 64 * 1024 * 1024 for file_name in src_files: full_file_name = os.path.join(src, file_name) if os.path.isfile(full_file_name): dest_file = os.path.join(newPath, file_name) # 用with语句自动管理文件句柄 with open(full_file_name, 'rb') as fsrc, open(dest_file, 'wb') as fdst: shutil.copyfileobj(fsrc, fdst, length=BUFFER_SIZE) print(f"搞定:{file_name}")
缓冲区越大,IO操作的次数就越少,网络共享场景下的速度提升会很明显,你可以多试几个值找到最适合你环境的大小。
二、更高效的替代复制方法
直接调用Windows原生工具(强推!)
Windows自带的robocopy和xcopy是专门为文件传输优化的,尤其是网络共享场景,性能比Python的原生IO操作强太多。用subprocess调用就行,还支持断点续传、错误重试这些实用功能:import os import subprocess def copyWithRobocopy(src, newPath): for file_name in os.listdir(src): full_file_name = os.path.join(src, file_name) if os.path.isfile(full_file_name): # 注意路径有空格的话要加引号,/J参数是专门给大文件用的无缓冲IO cmd = f'robocopy "{src}" "{newPath}" "{file_name}" /J' subprocess.run(cmd, shell=True, check=True) print(f"复制完成:{file_name}")robocopy还有一堆参数可以调,比如/R:3设置重试3次,/W:5设置重试间隔5秒,对付不稳定的网络特别有用。底层IO操作手动实现复制
如果想完全自己掌控复制流程,用os.open、os.read、os.write这种底层方法,能减少Python文件对象的封装开销,速度也不错:import os def copyWithLowLevelIO(src, newPath, buffer_size=64*1024*1024): for file_name in os.listdir(src): full_src = os.path.join(src, file_name) full_dest = os.path.join(newPath, file_name) if os.path.isfile(full_src): # 打开文件描述符 src_fd = os.open(full_src, os.O_RDONLY) dest_fd = os.open(full_dest, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o666) try: # 循环读写直到文件结束 while True: data = os.read(src_fd, buffer_size) if not data: break os.write(dest_fd, data) finally: # 一定要关闭文件描述符 os.close(src_fd) os.close(dest_fd) print(f"复制完成:{file_name}")
总结
如果是网络共享上的大文件复制,优先用robocopy,系统原生工具的优化最到位;如果必须用纯Python实现,那增大shutil.copyfileobj的缓冲区是最直接有效的办法。
内容的提问来源于stack exchange,提问作者Mario S
相关产品推荐
相关产品推荐

