os.walk漏空文件夹因不yield无子项的目录;pathlib.rglob返回path对象需转str;性能上rglob更优,大目录推荐os.scandir;符号链接易致死循环,须显式控制。

os.walk 为什么总漏掉空文件夹
它默认只遍历有内容的子目录,遇到空文件夹时 dirs 列表为空,但 os.walk 不会主动“返回”这个空目录本身——你看到的只是没进得去、也没被 yield 出来。
实操建议:
- 用
topdown=True(默认),并在每次迭代后检查当前root是否需要单独处理 - 若必须收集所有目录(含空的),别依赖
dirs的变化,改用pathlib.Path(root).iterdir()预扫一遍再决定逻辑分支 - 注意:修改
dirs列表(如dirs[:] = [...])能控制下层遍历范围,但对当前层是否“出现”无影响
pathlib.Path.rglob 与 os.walk 的路径类型差异
pathlib.Path.rglob 返回的是 Path 对象,而 os.walk 返回的是字符串路径(str)。这直接影响后续操作:比如直接传给 open() 没问题,但传给旧版 subprocess.run 或某些 C 扩展可能报 TypeError: expected str, bytes or os.PathLike。
常见错误现象:TypeError: expected str, bytes or os.PathLike, not PosixPath
实操建议:
- 统一转成字符串用
str(p),而不是p.__str__()或拼接 - 判断是否存在优先用
p.exists(),别用os.path.exists(str(p))—— 多此一举还丢掉 pathlib 的链式优势 - Windows 下注意
rglob('*.py')不区分大小写,但os.walk+fnmatch默认区分,行为不一致
大目录下 os.walk 性能卡在 stat 调用上
默认情况下,os.walk 对每个条目都调用 os.stat()(尤其在 follow_symlinks=False 时),大量小文件场景下 I/O 开销明显。而 pathlib.Path.rglob 在 Python 3.12+ 已优化为延迟 stat,只在需要时才触发。
性能影响示例:遍历含 50 万小文件的目录,os.walk 可能比 rglob 慢 2–3 倍
实操建议:
- 若只需路径名,不用文件属性,用
os.scandir()替代os.walk,它返回DirEntry,.stat()可选且缓存 - 避免在
os.walk循环里反复调用os.path.join(root, name),改用os.path.abspath()或提前拼好基路径 - Python 3.12+ 项目优先用
Path.rglob,除非要精确控制遍历顺序或需跳过特定层级
Windows 符号链接和 junction 点导致 os.walk 死循环
os.walk 默认不检测循环引用,遇到符号链接指向父目录(或 junction 指向同盘根目录)时,会无限深入。而 pathlib.Path.rglob 默认也不检测,但可通过 follow_symlinks=False(默认值)规避——不过要注意:Windows junction 点即使 follow_symlinks=False 仍可能被当作真实目录遍历。
错误现象:RecursionError: maximum recursion depth exceeded 或进程长时间无响应
实操建议:
- 始终显式传
follow_symlinks=False给os.walk,并配合os.path.islink()过滤 - 在 Windows 上处理未知来源路径时,先用
os.path.realpath()展开一次,再用集合记录已见路径做简易去重 - 不要依赖
pathlib.Path.resolve()来防循环——它本身就会陷入死循环,除非加strict=False
os.walk 还是 rglob,而是你得清楚自己要不要进符号链接、有没有权限读子目录、以及那个“空文件夹”到底是业务要求忽略,还是漏数据的关键点。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











