当前位置:首页 > 文章列表 > 文章 > python教程 > Python shutil.copyfileobj 怎样控制大文件复制缓冲区

Python shutil.copyfileobj 怎样控制大文件复制缓冲区

来源:17golang原创 2026-10-23 08:56:16 0浏览 收藏

用 shutil.copyfileobj() 复制大文件时,真正控制内存占用的是第三个参数 length。它表示每一轮从源对象读取的缓冲区大小:省略时由 Python 分块复制,传入正数时使用指定大小,传入负数则可能一次把剩余内容读入内存。生产代码通常应优先使用明确的正数,并根据输入流的性质调整。

官方文档地址:https://docs.python.org/3/library/shutil.html#shutil.copyfileobj

如果目标是稳定复制大内容,先把 length 当作“单次读取上限”来设计,而不是把它当作文件总大小。默认分块适合不确定的输入,正数适合需要控制内存的任务,负数只适用于你明确接受一次性读取的短数据。

先分清 length 的真实含义

copyfileobj(fsrc, fdst, length) 面向的是两个 file-like object,不要求它们一定来自普通文件。文件、BytesIO、HTTP 响应流和临时文件都可以提供类似的读取或写入接口。

写法内存语义适用判断
省略 length按内部块分段读取,避免无界的一次性加载输入规模不确定时的默认选择
length=1024 * 1024每次最多读取约 1 MiB希望明确控制单次缓冲区
length=-1不再按块循环,可能一次读取全部剩余内容只有短小且内存可控的输入才考虑

官方文档还特别说明:如果源对象当前的位置不是 0,复制只会从当前位置到末尾。这个细节很容易让“目标文件少了一截”被误判成缓冲区问题。

用正数缓冲区复制大文件

对于本地文件,建议以二进制模式打开,并把缓冲区值写成有名字的常量。下面的示例只表达复制边界,不把某个数值宣称为所有磁盘和网络环境的最佳值。

from pathlib import Path
from shutil import copyfileobj

CHUNK_SIZE = 1024 * 1024  # 每轮最多读取 1 MiB,限制复制阶段的临时内存
source = Path("backup.tar")
target = Path("backup-copy.tar")

with source.open("rb") as src, target.open("wb") as dst:
    copyfileobj(src, dst, length=CHUNK_SIZE)  # 让源流和目标流保持二进制类型
    dst.flush()  # 后续若要立即读取目标文件,先刷新写入缓冲区

这里的关键不是“1 MiB 一定最快”,而是把单次读取的边界显式化。缓冲区太小会增加循环和系统调用次数,太大则会抬高单个任务的瞬时内存;多任务并发复制时,应把每个任务的缓冲区一起估算。

Python copyfileobj 源流、正数缓冲区和目标流之间的结构关系说明图
图1:复制流边界说明图,查看源流、length 缓冲区和目标流的关系;这是静态结构图,不是运行截图。

按流类型做取舍,而不是盲目放大缓冲区

在高并发任务中,旧的“每次读取全部剩余内容”做法会把输入大小直接转化为单任务内存压力。更稳妥的设计是把源流、缓冲区和目标流分开考虑:

  • 本地大文件:使用固定正数,让内存占用与文件总大小脱钩。
  • 网络输入:用中等块大小换取吞吐和延迟的平衡,不因为网络慢就扩大到整个响应。
  • 临时文件或内存流:仍要关注源对象当前位置,目标对象若要马上读取则显式 flush() 或关闭。

这是一种架构取舍:用更多循环次数换取可预测的内存曲线。真正的“上线结果”应由目标环境中的吞吐、并发数、磁盘和网络条件共同决定,不能只凭一个示例值下结论。若复制任务由队列并发执行,可先按“任务数 × 单任务缓冲区”估算上界,再决定是否需要更小的块或更低的并发。

Python copyfileobj 默认分块、正数缓冲区和负数一次性读取的边界对比说明图
图2:缓冲区选择说明图,比较默认分块、正数 length 与负数 length 的内存边界;这是静态结构图,不是运行截图。

四个容易误判的边界

源流不是从开头开始。如果上游已经读过请求头、文件头或一部分数据,copyfileobj() 会从当前位置继续复制。需要从开头复制时,应由调用方先明确 seek(0),而不是修改缓冲区参数。

文本流和二进制流不能混用。文件内容是字节时使用 rb 与 wb;若把二进制读取结果写入文本流,可能触发类型错误。编码转换应放在明确的文本处理层,不要交给复制函数猜测。

复制完成不等于目标已经刷新。copyfileobj() 不保证目标流在函数返回时已经 flush。复制到可读的临时文件或内存流后,先执行 flush() 或关闭,再进行后续读取。

不要把负数当成“更大的缓冲区”。负数改变的是复制策略:它取消按块循环,可能一次读取所有剩余数据。只有短数据、内存边界明确的场景才适合使用。

相关问题

为什么复制后的文件为空?先检查目标流是否仍处于写入状态,以及读取前是否执行了 flush();如果是内存流,还要确认读取位置是否需要重新定位。

length 应该设置多大?没有脱离环境的固定答案。先根据并发数和可用内存设上界,再用实际吞吐观察调整;大文件场景优先保证可预测,而不是追求一次调用完成。

copyfileobj 会复制文件权限和时间吗?不会。它只复制 file-like object 的内容;如果还需要文件元数据,应另行选择 shutil.copy()、copy2() 或专门的元数据处理逻辑。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Python logging 怎样按模块切分日志级别Python logging 怎样按模块切分日志级别
上一篇
Python logging 怎样按模块切分日志级别
Linux cgroup v2 memory.swap.max 怎样限制交换空间
下一篇
Linux cgroup v2 memory.swap.max 怎样限制交换空间
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    611次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    650次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    682次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    645次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    469次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码