os.walk()遍历行为异常排查:为何目录遍历顺序突然改变?
关于os.walk()遍历顺序突变的原因分析&验证方案
先给你掰扯清楚一个关键认知:Python的os.walk()从来没保证过会按数字顺序(或者任何固定顺序)返回目录。它完全是跟着底层操作系统给的目录列表顺序走的——说白了就是你在终端敲ls不加参数时看到的顺序,和访达的排序逻辑根本不是一回事儿。你之前觉得它和访达数字排序一致,纯属巧合刚好系统返回的顺序符合预期而已。
可能导致顺序变化的两个核心原因
1. macOS系统升级(Sierra → High Sierra)的锅
High Sierra对文件系统做了大改动:默认换成了APFS(如果升级时转换了的话),哪怕没转APFS,对旧的HFS+也有底层实现调整。不同文件系统的目录项存储、枚举逻辑不一样,直接就会让os.walk()拿到的目录顺序变掉,这是最有可能的原因。
2. Python版本升级的可能性(概率较低)
虽然os.walk()本质是调用系统API,但也不能完全排除Python版本升级带来的细微变化。不过这个很好验证,咱们往下看。
怎么确认Python是否升级了?
打开终端,直接敲命令查版本就行:
# 查系统自带的Python2版本 python --version # 查你可能安装的Python3版本 python3 --version
如果你的脚本用了虚拟环境,记得先激活环境再查。对比你印象里之前用的版本,就能立刻知道有没有升级。
如何确保始终按数字顺序遍历?
既然os.walk()本身不兜底排序,那咱们手动来就行。针对你这种0001-0899的编号目录,直接对目录列表按数字值排序:
import os target_dir = "/你的目标目录路径" for root, dirs, files in os.walk(target_dir): # 把目录名字符串转成整数再排序,保证数字顺序 dirs.sort(key=lambda x: int(x)) # 接下来该干嘛干嘛,比如遍历子目录 for sub_dir in dirs: print(os.path.join(root, sub_dir))
划重点:修改dirs列表会直接影响os.walk()后续的递归遍历顺序,所以上面的写法能让整个递归过程都按数字顺序走,稳得一批。
内容的提问来源于stack exchange,提问作者rdv




