2013-03-06 28 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 
相關問題