Python中如何使用shutil模块高效复制大文件

因为电脑里不可描述的视频太多,准备清理下。用 py 写脚本,想快速分类并移动文件到指定文件夹,但是在用 shutil 模块复制视频文件的时候,耗时极长,一个 1g 大小的视频大概需要花费 1 分钟左右,而且期间电脑风扇狂转,本人用的 mbp13 寸,想问问大家这是什么情况,有没有更好的解决办法呢?


Python中如何使用shutil模块高效复制大文件
16 回复

用 mv 不要用 cp


shutil.copyfileobj(),配合合适的缓冲区大小,复制大文件最靠谱。

shutil.copy()shutil.copy2()在内部对小文件还行,但处理大文件时,它们会一次性读取整个文件到内存,容易爆内存。copyfileobj()是流式操作,读一块写一块,内存占用稳定。

关键就是那个length参数,它指定缓冲区大小。默认是16KB,对于大文件,特别是机械硬盘,调到1MB或几MB能显著提升速度,减少磁盘I/O次数。但别太大,否则内存占用又上去了。

这里有个例子,复制一个1GB的大文件,用8MB的缓冲区:

import shutil
import os

def copy_large_file(src, dst, buffer_size=8*1024*1024):
    """
    高效复制大文件
    :param src: 源文件路径
    :param dst: 目标文件路径
    :param buffer_size: 缓冲区大小,默认8MB
    """
    try:
        with open(src, 'rb') as fsrc:
            with open(dst, 'wb') as fdst:
                shutil.copyfileobj(fsrc, fdst, length=buffer_size)
        print(f"文件复制成功: {src} -> {dst}")
    except FileNotFoundError:
        print(f"错误: 源文件 {src} 不存在")
    except PermissionError:
        print(f"错误: 没有权限访问文件")
    except Exception as e:
        print(f"复制过程中发生错误: {e}")

# 使用示例
source_file = "path/to/your/large_file.iso"  # 你的大文件路径
destination_file = "path/to/destination/large_file_copy.iso"

copy_large_file(source_file, destination_file)

# 可选:验证文件大小
if os.path.exists(destination_file):
    src_size = os.path.getsize(source_file)
    dst_size = os.path.getsize(destination_file)
    if src_size == dst_size:
        print("文件大小验证通过")
    else:
        print("警告: 复制后文件大小不一致")

简单说,大文件复制就用copyfileobj(),缓冲区大小根据你的硬盘情况调一下。

我试试勒

os.rename 不能跨卷

还真是,谢谢🙏

但是为啥 copy 那么慢呢

move 比 copy 快是因为 move 在同文件系统下只是修改一下记录,没有复制操作。
操作系统的复制比 Python 快的话可能是因为系统有特别优化。而 Python 的 shutil 仅仅是同步读取然后同步写入。

<br>def copyfileobj(fsrc, fdst, length=16*1024):<br> """copy data from file-like object fsrc to file-like object fdst"""<br> while 1:<br> buf = fsrc.read(length)<br> if not buf:<br> break<br> fdst.write(buf)<br>

原来这样……那是挺慢的

mv 万一中途意外中断可就大麻烦。

13 寸 mbp,是机械硬盘么?

调用 cp 不如直接呼叫 rsync 来干这事,更可靠。mv 真的风险太大。

😢cp 和 rsync 是什么东东

并不会

rsync 是一个文件同步工具,支持断点续传

rsync 也能 move 文件吗?

#13 rsync --remove-source-files

#13 但是 rsync 还是复制文件然后删除,和同一文件系统下 mv 只修改文件记录相比肯定是慢太多

回到顶部