2013-03-06 32 views
2

我试图让Python中的某个目录下的所有孙子。出于性能方面的原因,我不想继续在循环中调用OS函数(这是一个网络文件系统)。这是我目前所拥有的。有没有更简单的方法来做到这一点?如何得到一个目录下的所有孙子在Python只有一个操作系统调用

dirTree = os.walk(root) 
children = [os.path.join(root, x) for x in dirTree.next()[1]] 
grandChildren = [] 
for root, dirs, files in dirTree: 
    if root in children: 
     for dir in dirs: 
      grandChildren.append(os.path.join(root, dir)) 

编辑:我不清楚我的os.walk调用是否懒惰。我的意图是,在我打电话后整棵树应该留在记忆中,但我不确定。

+0

你看了'unipath'模块? – 2013-03-06 20:16:51

+0

[This answer](http://stackoverflow.com/a/4117594/8747)可能会揭示出来。 – 2013-03-06 20:18:43

+0

你只对孙子或者第二世代和后代的所有后代感兴趣吗?也就是说,将'root/a/b/c/d'包含在搜索中还是排除在外? – 2013-03-06 20:21:01

回答

5

如果我收到了你的问题的权利。

可以使用水珠来获得文件或目录,给予通配符符号。例如将所有目录都放在“/ home /”里,你可以在列表中找到它。

glob.glob('/home/*/*/') 

或知道所有的文件,以及你可以做

glob.glob('/home/*/*') 
+0

这不是非常有用,因为你必须知道在每个目录的子目录的数目。 – msvalkon 2013-03-06 20:21:18

+0

jjujuma:''grandChildren = [dirpath.rstrip(os.sep)为glob.iglob中的dirpath('/ home/*/* /')]产生与您的代码相同的列表。 rstrip()会删除列表中目录路径上的尾随路径分隔符。 @msvalkon:我相信你错了。 – martineau 2013-03-06 22:46:15

+0

@martineau啊是的,我把'grandChildren'理解为'/ foo/bar'的所有子目录。 – msvalkon 2013-03-06 22:52:21

1

在POSIX也没有在Windows中,你不能让所有的数据在一个操作系统调用。至少,对于POSIX,将有三个每个目录(opendirreaddirclose),加上每个目录项一(stat)。


我相信接下来的操作会导致比您发布的操作系统更少的操作。是的,os.walk()调用是懒惰的;也就是说,整个树是在在从walk()回内存,但是调用next()过程中,而读零碎。

因此,我的版本将只读取1阶子孙的目录,并且将stat仅限于直系子孙。你的版本也会为所有的曾孙辈做这项工作,就像你的目录结构一样。

root='.' 
grandChildren = [] 
for kid in next(os.walk('.'))[1]: 
    x = next(os.walk(os.path.join('.', kid))) 
    for grandKid in x[1]: # (or x[1]+x[2] if you care about regular files) 
    grandChildren.append(os.path.join(x[0], grandKid)) 

或者作为一个列表的理解,而不是一个for循环:

import os 
root='.' 
grandChildren = [ 
    os.path.join(kid, grandKid) 
    for kid in next(os.walk(root))[1] 
    for grandKid in next(os.walk(os.path.join(root, kid)))[1]] 

最后,分解出os.walk s转换功能:

def read_subdirs(dir='.'): 
    import os 
    return (os.path.join(dir,x) for x in next(os.walk(dir))[1]) 

root='.' 
grandChildren = [ 
    grandKid 
    for kid in read_subdirs(root) 
    for grandKid in read_subdirs(kid)] 


从测试中,我们可以看到,我的版本呼叫 stat的次数要比只有曾孙的人少很多。

在我的主目录,例如,我跑我的代码(/tmp/a.py)和你们(/tmp/b.py)与root设置为'.'在每种情况下:

$ strace -e stat python /tmp/a.py 2>&1 > /dev/null | egrep -c stat 
1245 
$ strace -e stat python /tmp/b.py 2>&1 > /dev/null | egrep -c stat 
36049 
相关问题