os.walk bug?

Alex Martelli aleaxit at yahoo.com
Sat Dec 18 12:11:27 EST 2004


Adam DePrince <adam at cognitcorp.com> wrote:

> Each iteration of os.walk returns three parameters; one of those, dirs,
> is a list of directories within the current directory pointed at by
> root. 

Yes, it does.

> Am I correct to assume that you beleve that by changing the contents of
> dir you will affect how os.walk traverses the directories.  If so, that
> is your problem.

It's not a problem: it's a correct description of os.walk behavior.

> When looping in a for loop, it is generally good programming practice to
> assume that nothing you do within your loop will affect which
> root,dir,files tuples have been set aside to loop over.  It is likely
> that once os.walk was called, the items to be iterated over are
> predestined (i.e. assume you are iterating over a tuple.) 

"Likely"?  I think it's generally good programming practice to read the
docs.  help(os.walk) says:

When topdown is true, the caller can modify the dirnames list in-place
(e.g., via del or slice assignment), and walk will only recurse into the
subdirectories whose names remain in dirnames; this can be used to prune
the search, or to impose a specific order of visiting.  Modifying

and topdown is true by default.  The problem was just that the poster
was not using the right way to "modify the dirnames list in-place", as
he was looping on said list rather than a copy and yet modifying what he
was looping on (two suggestions i saw were "loop on a copy", once
obtained with the odd but popular Python idiom somelist[:], once with
the much more readable approach list(somelist)...).  The best
alternative is often to use a list comprehension, with somelist[:] on
the left of the assignment since you do need to modify in-place.  I.e.,
say that, generically speaking, you're trying (and failing) to do:

for item in alist:
    if isnasty(item):
        alist.remove(item)

changing the header to ``in alist[:]:'' or ``in list(alist):'' probably
makes this code work, but it still can't make it GOOD... good would be:

alist[:] = [item for item in alist if not isnasty(item)]


Alex
  



More information about the Python-list mailing list