2016-05-16 81 views
0

我正在搜索大型目錄以將舊歸檔歸類爲特定順序。我嵌入了一個遞歸調用的函數,當它找到一個文件路徑匹配搜索條件的目錄時,它將它添加到'found'字典fdict使用os.scandir停留在遞歸目錄搜索中

預期的結果是,當在沒有子目錄的目錄上調用該函數時,該函數完成時不執行任何操作並移回到一個級別。

運行時,它被卡在第一個目錄中,它找不到子目錄,只是遞歸調用當前目錄進行搜索,陷入循環。

下面是代碼摘要,任何洞察爲什麼它是循環將不勝感激。

def scan(queries, directory): 
    fdict = {} 
    def search(queries, directory, fdict): 
     for entry in os.scandir(directory): 
      if entry.is_dir(): 
       for x in queries: 
        if str(x) in entry.path: 
         fdict[str(x)] = entry.path 
         print("{} found and dicted".format(str(x))) 
        else: 
         search(queries, entry.path, fdict) 
      else: pass 
    search(queries, directory, fdict) 
    return fdict 
+0

請確保你沒有關注[符號鏈接](https://docs.python.org/3/library/os.html#os.DirEntry.is_symlink)嗎? –

回答

0

整個事情可以寫爲

import os 
# let qs be a list of queries [q] 
# root be the start dir 
for path, dirnames, filenames in os.walk(root): 
    for dirname in dirnames: 
     full_path = os.path.join(path, dirname) # optional (depends) 
     for q in qs: 
      if q in full_path: 
       # do whatever 

os.walk是遞歸的。您也可以執行一些set操作,以消除for q in qs。評論它是否不適合你。

+0

感謝os.walk的介紹。我以前沒有使用它,並且正在使用scandir來獲得速度,但是已經閱讀過,似乎在3.5中使用了scandir算法來散步。你能否在你提到的'set'操作中快速完成? – wirrell

+0

@GeorgeWorrall謝謝。關於'set'操作,我暗指一個特殊情況。也就是說有一個函數'f',這樣'query = f(full_path)'這意味着所有'full_path'都以同樣的方式包含'query'。然後在full_paths中引入一個genexp fulls =(f(p)),然後'matches = queries.intersection(fulls)'。製作這些'set's bdw。 –

+0

這很清楚,再次感謝! – wirrell

0

好吧,原來問題出在for x in queries:聲明中。

明顯的循環是由不好的設計造成的,這意味着只有queries列表中的第一個值與調用else語句之前的entry.path相比,並且在當前entry.path上調用搜索函數。

一旦達到沒有子目錄的目錄,它就會後退一個級別,並根據entry.path測試queries中的第二個條目。

儘管代碼最終會產生所需的結果,但這種方法將需要絕對的年齡(在這種情況下,queries是一個4000值長的列表!),並給出了檢查循環的外觀。

如果有人遇到類似問題,以下是未來參考的更正代碼。

def scan(queries, directory): 
    fdict = {} 
    def search(queries, directory, fdict): 
     for entry in os.scandir(directory): 
      if entry.is_dir(): 
       if entry.name in queries: 
        fdict[str(x)] = entry.path 
       else: 
        time.sleep(2) 
        search(queries, entry.path, fdict) 
      else: pass 
    search(queries, directory, fdict) 
    return fdict