0

I am studying the os.walk() method.

All the examples I've been able to find show the usage as:

for root, dirs, files in os.walk(trackeddir):
    for name in files:
        print(os.path.join(root, name))
    for name in dirs:
        print(os.path.join(root, name))
    ...

However, when I try: root, dirs, files = os.walk(trackeddir), I get an exception: "too many values to unpack (expected 3)"

I tried putting the output of os.walk() into a variable and seeing what is stored in that variable, during debug, but I was unable to see any "root", "files" or "dirs" I expected to see a tuple but, instead, I see an instance of 'generator'

I am a relatively "OK" Java developer and this new style of handling data in runtime is really confusing. Any help in trying to wrap my head around it will be hugely appreciated!

DraxDomax
  • 1,008
  • 1
  • 9
  • 28
  • 4
    You wouldn't expect `for x in thing` and `x = thing` to perform the same assignment to `x`, would you? Same here. The fact that you can do `for root, dirs, files in os.walk(whatever)` doesn't mean that `root, dirs, files = os.walk(whatever)` makes any sense. – user2357112 Mar 21 '21 at 14:08
  • 1
    You may want to read the documentation on Python [generators](https://wiki.python.org/moin/Generators). – larsks Mar 21 '21 at 14:08
  • Please clarify what you are asking. Are you wondering how a generator can be used in a for loop, or how each iteration can unpack to multiple variables? – MisterMiyagi Mar 21 '21 at 14:32
  • 3
    Thinking in Java terms, `os.walk` returns `Iterator`, where `DirectoryEntry` specifies the the path, the list of directories and list of files (since Java doesn't have tuples out of the box). You can't directly assign an iterator to a variable and expect to get the next entry. You either need to invoke `next`, or you need to use `for (DirectoryEntry d: treewalker)`. In Python it is analogous: use `next` to get one value, or use `for` to iterate over the entire iterable. – Amadan Mar 21 '21 at 14:33
  • 1
    Does this answer your question? [How does a Python for loop with iterable work?](https://stackoverflow.com/questions/1292189/how-does-a-python-for-loop-with-iterable-work) – MisterMiyagi Mar 21 '21 at 14:33
  • Does this answer your question? [Tuple unpacking in for loops](https://stackoverflow.com/questions/10867882/tuple-unpacking-in-for-loops) – MisterMiyagi Mar 21 '21 at 14:35
  • To further illustrate it, if you try `it = os.walk(trackeddir); entry = next(it)`, `entry` will be a tuple, which you could unpack using `root, dirs, files = entry`. (However, it will only be the information on the first entry that `os.walk` encounters.) – Amadan Mar 21 '21 at 14:48
  • all comments extremely enlightening! Thank you! – DraxDomax Mar 21 '21 at 16:28

1 Answers1

3

This is due to the fact that os.walk is a generator. When you iterate over a generator, it will yield the next element until there are no elements lefts. Note that you can define the generator in a variable and then get the next set of elements without a loop:

g = os.walk(tracckeddir)
r, d, f = next(g)

To return the entire set of elements which would be generated, you can apply list():

list(os.walk(trackeddir))
Mathieu
  • 5,410
  • 6
  • 28
  • 55