9

Alright, I'm working with a Bioloid Premium humanoid robot, and Mac OS X will not recognize it. So I wrote a Python script to detect changes in my /dev/ folder because any connection on a Linux-based system is still given a reference via a file descriptor. My code should work, however, when assigning three variable to the values that are returned by os.walk(top), I get a ValueError. Anyone know how I can fix this? I've used this function in the past, and it hasn't given me any trouble. My script btw is very rough, I wrote it in about 5 minutes or so.

Code:

root_o, dir_o, files_o = os.walk(top)

and the error is as follows.

Traceback (most recent call last):
  File "detectdevs.py", line 15, in <module>
    findDevs()
  File "detectdevs.py", line 11, in findDevs
    root_o, dir_o, files_o = os.walk(top)
ValueError: need more than 1 value to unpack

I did search around stackoverflow, and none of the ValueError issues I saw reference the os.walk() function.

Ech0riginal
  • 329
  • 1
  • 3
  • 7
  • I'm not sure about MacOSX, but on Linux, you can detect when devices are plugged in using [udev](http://en.wikipedia.org/wiki/Udev). – unutbu Mar 01 '13 at 14:06
  • The MacOSX equivalent of udev appears to be [diskutil activity](http://apple.stackexchange.com/questions/46951/is-there-a-mac-equivalent-for-udev-folder-on-linux). – unutbu Mar 01 '13 at 14:36

4 Answers4

23

os.walk returns an iterator that yields three-tuples, not a three-tuple:

for root, dirs, files in os.walk(top):
    # do stuff with root, dirs, and files

 

    In [7]: os.walk('.')
    Out[7]: <generator object walk at 0x1707050>

    In [8]: next(os.walk('.'))
    Out[8]:
    ('.',
     ['.vim',
      '.git',
       ...],
     ['.inputrc',
      ...])
Pavel Anossov
  • 60,842
  • 14
  • 151
  • 124
7

You need to iterate over os.walk():

for root_o, dir_o, files_o in os.walk(top):

or store the iterator first, then loop:

walker = os.walk(top)
for root_o, dir_o, files_o in walker:

The return value of the callable is a generator function, and only when you iterate over it (with a for loop or by calling next() on the iterator) does it yield the 3-value tuples.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
3

Try this

for root_o, dir_o, files_o in os.walk(top)
    print root_o, dir_o, files_o

os.walk is a generator and you need to iterate over it.

danodonovan
  • 19,636
  • 10
  • 70
  • 78
1

Perhaps what's more useful here is where it says "more than 1 value to unpack".

See, in python, you "unpack" a tuple (or list, as it may be) into the same number of variables:

a, b, c = (1, 2, 3)

There are a few different errors that turn up:

>>> a, b, c = (1, 2, 3, 4, 5, 6)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack

>>> a, b, c = (1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: need more than 2 values to unpack

Specifically, the last error is the type of error you're getting. os.walk() returns an iterator, i.e. a single value. You need to force that iterator to yield before it will start to give you values you can unpack!

This is the point of os.walk(); it forces you to loop over it, since it's attempting to walk! As such, the following snippet might work a little better for you.

for root_o, dir_o, files_o in os.walk(top):
    make_magic_happen(root_o, dir_o, files_o)
Ben Stott
  • 2,218
  • 17
  • 23