[Tutor] skip some directories

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Tue May 31 09:41:37 CEST 2005



> At the end, i found the way of make it:
>
> dirBase = ['misc','TTF','Type1','CID','100dpi','75dpi','encodings', 'util']
>
> for root, dirs, files in os.walk(dirName):
>     print dirs  # for checking all directories that i have at beginning
>     for name in dirs:
>         if name in dirBase:
>             dirs.remove(name)


Hi Jonas,


What's happening is a consequence of in-place deletion in lists: when we
delete from the same collection that we iterate across, we run into the
real possiblity of "yanking the rug" right underneath the loop.  The for
loop:

   for name in dirs:

combined with deletions on 'dirs', is a likely culprit for the problem.


Let's take a simpler loop to make it easier to see the potential bug. Say
that we have a 'for' loop, like this:

######
names = ['bill', 'ted']
for n in names:
    print n
    names.remove(n)
######

What do you expect to see here?  Try running it, and see if it matches
with what you expect.


If it helps, we can do a rough translation of this into a while loop with
an explicit index counter:

######
names = ['bill', 'ted']
i = 0
while i < len(names):
    print names[i]
    names.remove(names[i])
    i = i + 1
######


One common way to avoid the problem is to iterate across a copy of the
list when we do things that change the structure of our list:

######
names = ['bill', 'ted']
for n in names[:]:        ### List slicing does a list copy
    print n
    names.remove(n)
assert names == []
######

Here, we use a trick by taking a "slice" of the whole list.  A similar
approach should fix the bug in your code.


Best of wishes to you!



More information about the Tutor mailing list