Python的os.walk出错?

0 投票
2 回答
1382 浏览
提问于 2025-04-15 23:45

os.walk 的文档(http://docs.python.org/library/os.html? highlight=os.walk#os.walk)提到,我可以通过从目录列表中移除不想遍历的目录来跳过它们。文档中的一个明确示例是:

import os
from os.path import join, getsize
for root, dirs, files in os.walk('python/Lib/email'):
    print root, "consumes",
    print sum(getsize(join(root, name)) for name in files),
    print "bytes in", len(files), "non-directory files"
    if 'CVS' in dirs:
        dirs.remove('CVS')  # don't visit CVS directories

我在使用 ActivePython 2.6.2 时发现了不同的行为。具体来说,对于以下代码:

>>> for root,dirs,files in os.walk(baseline):
...     if root.endswith(baseline):
...             for d in dirs:
...                     print "DIR: %s" % d
...                     if not d.startswith("keep_"):
...                             print "Removing %s\\%s" % (root,d)
...                             dirs.remove(d)
...
...     print "ROOT: %s" % root
...

我得到了这个输出:

DIR: two
Removing: two
DIR: thr33
Removing: thr33
DIR: keep_me
DIR: keep_me_too
DIR: keep_all_of_us
ROOT: \\mach\dirs
ROOT: \\mach\dirs\ONE
ROOT: \\mach\dirs\ONE\FurtherRubbish
ROOT: \\mach\dirs\ONE\FurtherRubbish\blah
ROOT: \\mach\dirs\ONE\FurtherRubbish\blah\Extracted
ROOT: \\mach\dirs\ONE\FurtherRubbish\blah2\Extracted\Stuff_1
...

这是什么情况?为什么 \\mach\dirs\ONE 没有被移除?它明显不是以 "keep_" 开头的。

2 个回答

2

你没有把它从 dirs 列表中移除。如果你真的移除了,你应该能看到“Removing”的打印输出,对吧?

for d in dirs 改成 for d in list(dirs),这样在遍历 dirs 列表的时候就可以安全地移除其中的项目。

或者你也可以直接写:

dirs[:] = [d for d in dirs if not d.startswith("keep_")]
5

因为你在遍历列表 dirs 的时候,同时又在修改它。这导致 ONE 被跳过了,根本没有被查看。对比一下:

>>> a = [1, 2, 3]
>>> for i in a:
    if i > 1:
        a.remove(i)


>>> a
[1, 3]

撰写回答