不同文件路径的解包 os.walk 不一致错误

Unpacking os.walk inconsistent errors for different filepath

基础Python问题。

正在使用 os.walk 函数,看到不一致的错误消息。 下面的示例 o/p:

Python 3.6.2 (default, Jul 18 2017, 14:08:57)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> root, dir, files = os.walk('.')  # ------> **no error**
>>> root, dir, files = os.walk('/')  # ------> **error #1**
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)
>>> root, dir, files = os.walk('/usr/bin') # ------>**error #2**
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 1)
>>>

我的理解是 os.walk returns 生成器,所以错误 #2 对我来说很有意义。返回一个生成器值,但我解包为 3 个值。

所以:

  1. 为什么我在 os.walk('.')
  2. 时没有收到任何错误
  3. 为什么错误 #2 和 #1 不同。

编辑 1:

玩了一下,发现python所在位置运行影响执行,因为“.”的意思。变化。

raghu$ pwd
/Users/raghu/PycharmProjects/Fib
raghu$ python
Python 3.6.2 (default, Jul 18 2017, 14:08:57)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> root, dir, files = os.walk('.')  # ------>**no error**
>>> ^D
raghu$ cd ..
raghu$ pwd
/Users/raghu/PycharmProjects
raghu$ python
Python 3.6.2 (default, Jul 18 2017, 14:08:57)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> root, dir, files = os.walk('.')  # ------>**error**
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)

来自文档:

For each directory in the tree rooted at directory top (including top itself), it yields a 3-tuple (dirpath, dirnames, filenames).

因此,在每种情况下,产生的元组数量可能不同,这会导致您出现问题。

当你解包时,你耗尽了右边的迭代器。您没有得到分配给 root, dirs, filenamesdirpath, dirname, filenames 元组。

尝试将os.walk(<value)的第一个结果(即第一个yield)分配给root,然后,将第二个结果(second yield)分配给dirs最后,第三次屈服于 file。如果产生更多(或更少!)的结果,就会出现错误。如果恰好返回三个,它似乎有效。

因此,在第一种情况下,这只是运气,3 结果返回给您并分配给您(3 个包含 dirpath, dirname, filenames 的元组!)。

'/usr/bin' usually 不包含任何子目录,这就是为什么你在那里得到不同的错误(只执行 1 个三元组 yield)。

使用 '/' 您还可以返回更多数量的三元素元组,因此您会得到相应的错误。

您可以通过检查生成器生成的项目数量来大致了解一下:

>>> from os import walk
>>> len(list(walk('.')))
2300
>>> len(list(walk('/')))  # this is really dumb
127242
>>> len(list(walk('/usr/bin')))
1

正如您在最后一个示例中看到的那样,只生成了一个 3 元素元组。如果您找到 len(list(walk('folder'))) == 3 所在的文件夹,解压将起作用。

(阅读:迭代时)os.walk(...) 产生的每个 值是一个三元组。你的代码表现得像函数returns一个这样的三元组,但它真正的意思是"expect exactly 3 directories in this directory tree and give (misleading) names to the (tuple of) information about each".