如何高效优化按文件类型批量复制文件的Python函数?
大文件批量复制的高效优化方案
先说说你原代码里几个影响效率和可靠性的问题:
- 用
source + "\\" + fs拼接路径,不仅跨平台兼容性差,还容易因为路径格式问题出错 - 单线程挨个复制,大量文件时IO等待会浪费很多时间
- 靠
len(listdir(destination)) != 0判断复制成功完全不合理——目标目录本来有文件的话,就算复制失败也会打印成功 - 依赖全局变量
raw_folder、jpg_folder,函数复用性太差
下面给几个不同场景的高效优化方案:
一、Python内最优:多线程并行复制
文件复制是IO密集型操作,多线程可以利用等待磁盘IO的时间处理其他文件,批量复制时效率提升非常明显。用concurrent.futures.ThreadPoolExecutor实现:
import os import shutil from concurrent.futures import ThreadPoolExecutor def copy_single_file(file_path, target_folder): try: # copy2比copy多保留文件元数据(修改时间、创建时间等),更实用 shutil.copy2(file_path, target_folder) return True except Exception as e: print(f"复制失败 {file_path}: {str(e)}") return False def main_copy(source, raw_folder, jpg_folder): success_count = 0 total_count = 0 # 用scandir遍历文件,比listdir+isfile快很多,减少系统调用 with os.scandir(source) as entries: file_entries = [entry for entry in entries if entry.is_file()] total_count = len(file_entries) if not file_entries: print("源目录里没文件可复制") return # 线程数可以根据磁盘性能调整,一般设为CPU核心数的2-4倍就行 with ThreadPoolExecutor(max_workers=8) as executor: futures = [] for entry in file_entries: if entry.name.endswith('.ARW'): futures.append(executor.submit(copy_single_file, entry.path, raw_folder)) else: futures.append(executor.submit(copy_single_file, entry.path, jpg_folder)) # 统计成功复制的文件数 for future in futures: if future.result(): success_count += 1 print(f"复制完成:成功 {success_count}/{total_count} 个文件")
优化点说明:
- 多线程并行处理,把磁盘IO的等待时间利用起来
- 用
os.scandir替代原有的listdir+isfile,减少不必要的系统调用,遍历速度更快 - 用
shutil.copy2保留文件元数据,比原代码的copy更实用 - 取消全局变量,把目标文件夹作为参数传入,函数更灵活
- 增加错误捕获和复制统计,替代原有的不合理成功判断逻辑
二、极端大文件/超大量文件:调用系统原生命令
如果Python的方案还是不够快,直接用系统级的复制工具,这些工具都是原生实现,性能拉满:
Windows 用 robocopy
自带多线程复制、断点续传,适合超大文件:
import subprocess def batch_copy_robocopy(source, raw_folder, jpg_folder): # 复制所有ARW文件,8线程,失败重试3次 subprocess.run([ "robocopy", source, raw_folder, "*.ARW", "/MT:8", "/R:3", "/W:1" ], check=True, shell=True) # 复制除ARW外的其他文件 subprocess.run([ "robocopy", source, jpg_folder, "*.*", "/MT:8", "/R:3", "/W:1", "/XF", "*.ARW" ], check=True, shell=True) print("复制完成")
Linux/macOS 用 rsync
高效的文件同步工具,支持增量复制,适合大量文件场景:
import subprocess def batch_copy_rsync(source, raw_folder, jpg_folder): # 复制ARW文件 subprocess.run( f"rsync -avz --include='*.ARW' --exclude='*' {source}/ {raw_folder}", shell=True, check=True ) # 复制其他文件 subprocess.run( f"rsync -avz --exclude='*.ARW' {source}/ {jpg_folder}", shell=True, check=True ) print("复制完成")
内容的提问来源于stack exchange,提问作者LoUso DeBasura
相关产品推荐
相关产品推荐

