最可靠方式是直接调用 shutil.disk_usage(),需传入已存在的目录路径,返回字节级剩余空间(已扣保留块),容器或网络文件系统中可能抛 notimplementederror,判断空间是否足够应预留安全余量。

用 shutil.disk_usage() 获取剩余空间最可靠
直接调用 shutil.disk_usage() 是 Python 3.3+ 中判断磁盘剩余空间的首选方式,它返回的是字节级原始数据,不受文件系统块大小或权限影响,比手动解析 df 输出或检查 os.statvfs() 更简洁稳定。
关键点:传入路径必须是**已存在的目录**(不能是文件或不存在的路径),函数会自动定位到该路径所在挂载点:
import shutil
total, used, free = shutil.disk_usage("/tmp") # 注意:传目录,不是文件路径
print(f"剩余: {free} 字节 ({free // (1024**3)} GB)")
- 如果传入
"/tmp/nonexistent.txt"会报OSError: [Errno 2] No such file or directory -
free值是操作系统报告的“非特权用户可用空间”,通常已扣除保留块(如 ext4 的 5% reserved space) - 在容器或某些网络文件系统中,
shutil.disk_usage()可能抛出NotImplementedError,需兜底处理
判断“是否足够”要预留安全余量
仅比较目标文件大小和 free 值往往不够——写入过程可能触发日志、元数据更新、临时缓冲,且多个进程可能并发写入。硬性等于判断容易失败。
实操建议:
- 对小文件(free >= 文件大小 * 1.2
- 对大文件(>100 MB):至少预留 500 MB 或 5% 空间(取较大值)
- 若目标路径在 Docker volume 或 NFS 上,建议额外 +10% 余量(因底层可能有额外开销)
- 避免用
os.path.getsize()获取待写文件大小——如果文件还没生成,得用预估大小(如压缩前原始数据量 × 压缩率)
跨平台时注意 Windows 和 Linux 的路径处理差异
shutil.disk_usage() 在 Windows 上接受盘符(如 "C:" 或 "C:\"),Linux/macOS 要求绝对路径(如 "/home")。传错格式会直接报错。
安全写法:
import os import shutil <p>def get_free_space(path): if os.name == "nt": # Windows drive = os.path.splitdrive(os.path.abspath(path))[0] return shutil.disk_usage(drive + "")[2] else: return shutil.disk_usage(os.path.dirname(path))[2]</p>
- 不要依赖
pathlib.Path(path).anchor判断盘符,Windows 下"./data/file.txt"的 anchor 是空字符串 - Linux 下传
"/"和"/home"可能返回不同结果(如果/home是独立挂载分区) - 容器内应用应以写入目标目录为准(如
"/app/output"),而不是代码所在路径
写入前校验后仍失败?可能是权限或 inodes 耗尽
即使 free > 文件大小,写入仍可能失败。常见原因不是空间不足,而是:
-
PermissionError: [Errno 13] Permission denied—— 目录可读但不可写,或父目录无执行权限(Linux) -
OSError: [Errno 28] No space left on device—— 实际是 inodes 耗尽(df -i查看),尤其大量小文件场景 - 磁盘配额(quota)限制了当前用户,
shutil.disk_usage()不反映该限制 - 文件系统只读挂载(
mount | grep ro),此时free非零但无法写入
真正健壮的检查需要组合判断:先查空间,再试创建临时文件(touch 级别),最后清理。但要注意避免在生产路径下留垃圾文件。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











