Python 拷贝大文件时如何选择合适的分片大小?
python 拷贝大文件一般套路是:
with open(src_file, "rb") as fr, open(dst_file, 'wb') as fw: # fr 读文件
while True:
data = fr.read(4096)
if not data:
break
fw.write(data)
后面跟一些异常处理,4096 这个是 4 KB,这个大小受什么因素影响?
写 1 * 1024 * 1024 行吗?我感觉性能完全够啊
Python 拷贝大文件时如何选择合适的分片大小?
1MB 当然可以。4KB 很可能就是随便写的一个数。
但是一般不会用 Python 去追求性能。高性能复制大文件还是直接走系统工具比较好吧。
在Python里拷贝大文件,用分片(chunk)来读写是标准做法,能有效控制内存。分片大小的选择没有绝对标准,得看你的场景。
核心原则:在内存占用、系统调用开销和磁盘I/O效率之间找平衡。
- 默认值(通常够用):很多库(如
shutil.copyfileobj)默认用16KB或64KB。这是一个安全的起点,适用于绝大多数情况。 - 内存考虑:分片越大,单次占用内存越多。如果你在内存受限的环境(如嵌入式设备、低配VPS),建议用较小的值,如4KB、16KB或64KB。
- 性能调优(高级场景):
- 对于机械硬盘(HDD),较大的分片(如128KB、256KB甚至1MB)可以减少磁头寻道次数,可能提升连续读写速度。
- 对于固态硬盘(SSD) 和现代操作系统,较小的分片(如64KB)通常也能跑满带宽,分片大小的影响变小。
- 网络文件系统或远程拷贝时,可能需要匹配网络包大小或协议块大小。
给你一个实用的代码示例和测试思路:
import shutil
import time
def copy_file_chunked(src, dst, buffer_size=64*1024):
"""使用指定分片大小拷贝文件"""
with open(src, 'rb') as fsrc:
with open(dst, 'wb') as fdst:
shutil.copyfileobj(fsrc, fdst, buffer_size)
# 测试不同分片大小的耗时
src_file = 'large_file.iso' # 你的大文件
dst_template = 'copy_test_{}.iso'
chunk_sizes = [4*1024, 16*1024, 64*1024, 256*1024, 1024*1024] # 4KB, 16KB, 64KB, 256KB, 1MB
for size in chunk_sizes:
dst_file = dst_template.format(size)
start = time.time()
copy_file_chunked(src_file, dst_file, buffer_size=size)
elapsed = time.time() - start
print(f"Buffer {size//1024}KB: {elapsed:.2f} seconds")
直接建议:从64KB开始,如果遇到性能瓶颈,再用上面的方法实测调整。
简单说,别想太复杂,64KB是个靠谱的起点。
为啥不用标准库 shutil,搞这种没人用的所谓套路
自己对比测试一下不就知道了
怕受随机因素影响就多做几次嘛
文件系统 block size 一般是 4k 吧
4KB 不是随机的一个数,Block device 的读操作是按照 block size 来的,读操作按照 block size align 才会更快( size 是 block size 的倍数)。
我写了一坨,但是后面的内容不知道为啥就是在 V2EX 发不出来,链接也发不出来…
我贴下 gist 链接转成的 base64 吧,查看方式:
echo aHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vbGFpeGludGFvLzE0MTJmYTAwOTg5M2VkNDYwMGNmMTE0OGVkMDRhOWIxCg== | base64 -D
希望你能解答你的疑惑。
和 block size 没有关系,你读的文件早就中间有文件系统层
应用程序 — 文件系统层 — 块设备层 — scsi/nvme/mtd… — 硬件
如果你的程序是直接读写块设备而不是文件系统(常见的有镜像烧写软件),再考虑 block size 的问题。
直接读写文件时,文件系统会处理好这些低级细节并执行缓冲和缓存。
为什么这个值要大:
因为 IO 操作(不仅 IO 操作,是全部的系统调用)是很消耗 CPU 的(涉及特权级别切换等耗时操作,特别是 Intel 漏洞使这方面更加剧了)。对于一个文件而言,缓冲区越大意味着调用系统调用的次数越少。
不过 block size 不一定是 4K 吧。
4k 是 Linux 的 page size 啊,这是文件缓存层层读文件的最小单位,即使应用层只读一个字节真实也会加载一个页缓存下来。少于一个 page 读多次会浪费 cpu 时间。详询 File Page Cache
嗯,不一定。 不过一般是 4k,我那个链接后面有说可以用 stat 看 block size,只要是 block size 的倍数就可以
正确的拷贝大文件的正确套路是。。。。。有系统 API 就直接用系统 API,cpython/blob/master/Lib/shutil.py#L227
发个 github 链接需要验证手机号码?这是啥套路?
python 读取大文件的方式: https://www.cnblogs.com/lowmanisbusy/p/10087071.html
感谢回复。
如果不是需要知道每一行内容的话,rb 速率比 r 高,而且安全一些,
因为 r 遇到一些特殊字符还有可能提前退出。
另外这边讨论的是拷贝不是读取[捂脸]


