顺手补个关键点:Path.walk() 这种剪枝写法要在 top_down=True 下才好用,默认就是这个;如果改成自底向上,先改 dirnames 就来不及了。像要排 .git、node_modules 这种目录时,这点挺重要。
Python 3.12+:`Path.walk()` 省掉一层 `os.walk` 的样板
第 2 页HosuLv1
FinleyLv1
如果要排除的目录多一点,我一般会直接用一份集合配合切片改 dirnames[:],比一个个 remove() 顺手点,也更不容易漏。比如 skip = {'.git', 'node_modules'} 这样。
问问Lv1
补一个容易踩的点:要剪枝的话别写 dirnames = [...],得原地改,比如 dirnames[:] = [d for d in dirnames if d != '.git']。
不然只是换了个局部变量,遍历本身还是会照着旧列表往下走。
uitfLv1
别熬夜啦Lv1
uitfLv1#15 对,这个点很关键。
dirnames一定得原地改,像dirnames[:] = [...]这种才会真的影响遍历。我一般还会把要排除的目录先放进一个集合里,后面过滤时一眼就能看懂,顺手也比较不容易漏。
补个我会写的版本:
skip = {'.git', 'node_modules', '__pycache__'}
for dirpath, dirnames, filenames in root.walk():
dirnames[:] = [d for d in dirnames if d not in skip]
for name in filenames:
if not name.endswith('.py'):
continue
print(dirpath / name)
这样剪枝和文件过滤分开,读起来会直一点。
Ryan小满Lv1
如果还得兼容 3.11,我一般会先包一层判断:有 Path.walk() 就走它,没有就回退到 os.walk()。
这样主逻辑不用分两套,后面改起来也轻一点。
雾很大Lv1
顺手补个容易漏的点:如果目录里可能有 A.PY 这种大写后缀,p.suffix == '.py' 会直接漏掉。跨平台一点的话,我会写成 name.lower().endswith('.py')。
小事,但扫代码仓库时挺省心。
JonahLv1
HosuLv1
再补一个细节:Path.walk() 遇到权限问题时可以配 on_error,自己决定是跳过还是记一笔,不用整趟直接断掉。扫仓库里那种脏目录时挺省心。