2016-03-01 174 views
0

我試圖在網絡驅動器O:\上找到所有.xlsm文件(並獲取它們的統計信息),前提是它們不在名爲Test的文件夾中。我正在使用os.walk並切換到scandir.walk,因爲它更快。我現在只受到網絡速度的限制。這段代碼似乎在腳本和網絡驅動器之間有很多交互。我的代碼如下。有沒有辦法加速這個可能使用批處理文件?我在Windows上。os.walk/scandir網絡驅動器上的速度太慢

from scandir import scandir, walk 
import sys 

def subdirs(path): 
    for path, folders, files in walk(path): 
     if 'Test' not in path: 
      for sub_files in scandir(path): 
       if '.xlsm' in sub_files.path: 
        yield subfiles.stat() 

for i in subdirs('O:\\'): 
    print i 

回答

3

你被明確雙掃描每一條路徑,一旦隱含通過walk,然後再重新scandir荷蘭國際集團的pathwalk返回無緣無故。 walk已經返回files,所以內循環可避免雙重掃描通過只使用它被賦予了什麼:

def subdirs(path): 
    for path, folders, files in walk(path): 
     for file in files: 
      if '.xlsm' in file: 
       yield os.path.join(path, file) 

爲了解決問題,更新,你可能會想無論是複製現有scandir.walk代碼並修改它將返回list s的DirEntry s而不是list s的名稱,或者爲您的特定需求編寫類似的特殊套裝代碼;無論哪種方式,這將允許您避免雙重掃描,同時保持scandir的特殊低開銷行爲。例如:

def scanwalk(path, followlinks=False): 
    '''Simplified scandir.walk; yields lists of DirEntries instead of lists of str''' 
    dirs, nondirs = [], [] 
    for entry in scandir.scandir(path): 
     if entry.is_dir(follow_symlinks=followlinks): 
      dirs.append(entry) 
     else: 
      nondirs.append(entry) 
    yield path, dirs, nondirs 
    for dir in dirs: 
     for res in scanwalk(dir.path, followlinks=followlinks): 
      yield res 

然後,您可以取代你的walk有像這樣使用(我還補充說,在他們Test,因爲根據他們的所有目錄和文件梅乾目錄將被拒絕你的原碼的代碼,但你還是會遍歷這些不必要的):

def subdirs(path): 
    # Full prune if the path already contains Test 
    if 'Test' in path: 
     return 
    for path, folders, files in scanwalk(path): 
     # Remove any directory with Test to prevent traversal 
     folders[:] = [d for d in folders if 'Test' not in d.name] 
     for file in files: 
      if '.xlsm' in file.path: 
       yield file.stat() # Maybe just yield file to get raw DirEntry? 

for i in subdirs('O:\\'): 
    print i 

順便說一句,你可能要仔細檢查是否已正確安裝/內置的C加速器scandir_scandir。如果_scandir未構建,則scandir模塊使用​​提供回退實現,但它們明顯較慢,這可以解釋性能問題。嘗試在交互式Python會話中運行import _scandir;如果它提高了ImportError,那麼你沒有加速器,所以你正在使用緩慢的回退實現。

+0

唯一的問題是,我放鬆了與通常需要通過os.stat()獲取的文件相關的其他變量,參見:https://github.com/benhoyt/scandir – user2242044

+0

@ user2242044:我知道'scandir'(我經常傳福音),但是你的原始代碼只是「產出」的路徑,而不是'DirEntry'對象;你沒有使用free/cached'stat'行爲。如果你需要'stat'信息,你可能想複製'scandir.walk'實現並修改它以返回'dirnames'和'filenames'的原始DirEntry對象的'list',而不是返回' 'str'名單'。這是兩全其美的。單次掃描,無重複性統計。或者只是實現專門用於您的用例的自己的遞歸函數。 – ShadowRanger

+0

@ ShadowRanger ..感謝您的澄清。我試圖簡化SO問題的代碼,但認爲我失去了一些意圖。雙重迭代是因爲我試圖避免迭代一些文件夾,我想獲得統計收益率。修改了原來的問題。謝謝! – user2242044