最稳妥的文件大小统计方法是用 os.walk() 遍历目录,拼接完整路径后调用 os.path.getsize();需注意权限跳过、中文路径兼容性,并避免 shell 命令解析风险。

用 os.walk() 遍历并累加文件大小最稳妥
直接用 os.listdir() 或 glob 容易漏掉嵌套子目录里的文件,而 os.walk() 能自然处理任意深度的目录结构。它返回的是三元组 (root, dirs, files),其中 files 是当前目录下的文件名列表,配合 os.path.getsize() 就能逐个统计。
- 必须用
os.path.join(root, file)拼出完整路径,否则getsize()会因找不到文件报OSError: [Errno 2] No such file or directory - 遇到权限不足的目录(比如
/proc下某些子目录),os.walk()默认会跳过,不抛异常——这是好事,但如果你需要日志提示,得手动捕获PermissionError - 对超大文件(如几十 GB 的视频),
getsize()很快,它只读文件元数据,不读内容
用 pathlib 写法更简洁但要注意 Python 版本
pathlib.Path 的 rglob() 方法一行就能拿到所有文件路径,适合 Python 3.5+。写法干净,但默认不区分文件/目录,得加 .is_file() 过滤。
-
Path("my_folder").rglob("*")会把目录也列出来,必须写成[p for p in Path("my_folder").rglob("*") if p.is_file()] -
p.stat().st_size和os.path.getsize(p)效果一样,但前者在 Windows 上对符号链接行为略有差异(默认跟随链接) - 如果路径含中文或特殊字符,
pathlib处理更鲁棒,不用额外编码转换
避免用 du -sh 这类 shell 命令封装
虽然 subprocess.run(["du", "-sh", "folder"], capture_output=True) 看似省事,但实际问题不少:输出格式依赖 locale(中文系统可能显示“4.2M”而非“4.2M”)、单位不统一(K/M/G 混用)、跨平台失效(Windows 没 du)。
- 解析
du输出需正则匹配,容易被文件名里的空格、换行、制表符搞崩 - Python 自己算总和更可控,比如想排除
.git或__pycache__目录,os.walk()里直接dirs[:] = [d for d in dirs if d not in {"__pycache__", ".git"}]就能剪枝 - 若真要调外部命令,优先选
du -sb(bytes 级别,无单位),再用int(line.split()[0])提取,但依然不如原生方案稳定
统计结果按大小排序或分组时别直接用字节值
原始字节数看着反人类,展示前得转成 KiB/MiB/GiB。别用 / 1024 硬除——那是十进制,IEC 标准该用 / 1024.0 并保留小数位;更关键的是,排序时如果先转字符串再排,会变成字典序("900KB" > "1.2GB"),必须保持数值比较。
- 推荐函数:
def fmt_size(n): units = ["B", "KiB", "MiB", "GiB"]; for u in units: if n - 排序文件列表时,key 写成
lambda p: p.stat().st_size,不是lambda p: fmt_size(p.stat().st_size) - 如果要按扩展名分组统计,用
collections.defaultdict(int)累加,注意Path.suffix返回".py",而Path.suffixes可处理.tar.gz
真正卡住人的往往不是遍历本身,而是路径拼错、没过滤目录、或者排序/格式化时用了字符串比较。动手前先在小目录试一次 print 出几个 os.path.getsize() 结果,比盯着文档猜强得多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











