def walk(top, topdown=True, onerror=None, followlinks=False):
#这是2.7 os.walk的源码
islink, join, isdir = path.islink, path.join, path.isdir
try:
names = listdir(top) #获取top目录下的所有名称
except error, err:
if onerror is not None:
onerror(err) #错误处理,skip掉
return
#正文开始
dirs, nondirs = [], [] #用来存储文件夹与非文件夹的数组
for name in names: #遍历top目录下的所有子路径
if isdir(join(top, name)):
dirs.append(name) #如果子路径指向文件夹,只将其存储到dirs数组中用于接下来的递归
else:
nondirs.append(name) #如果子路径指向文件,将其存储至nondirs数组
if topdown:
yield top, dirs, nondirs # yield出第一组结果
for name in dirs:
new_path = join(top, name) # 遍历刚才的文件夹list, 准备walk root下的子文件夹
if followlinks or not islink(new_path):
#如果不是link, 那么就是文件夹,那么就需要看看它下面的目录是什么情况。
for x in walk(new_path, topdown, onerror, followlinks):
yield x # 返回walk的结果, for循环类似于启动生成器的一个trigger
if not topdown:
建议你看看
生成器
/yield
,你也可以看看两次执行list(os.walk(path))返回的值。看完你才能大致了解为什么执行第二次list(generator)不会有任何结果。这个生成器你可以把它当成类似于文件读取,只不过它不提供seek操作,所以第一次你读到了尾,第二次再往下就读不出什么来了。下面是os.walk的源码,我写了注释,你自己看看。