你被明確雙掃描每一條路徑,一旦隱含通過walk
,然後再重新scandir
荷蘭國際集團的path
walk
返回無緣無故。 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
,那麼你沒有加速器,所以你正在使用緩慢的回退實現。
唯一的問題是,我放鬆了與通常需要通過os.stat()獲取的文件相關的其他變量,參見:https://github.com/benhoyt/scandir – user2242044
@ user2242044:我知道'scandir'(我經常傳福音),但是你的原始代碼只是「產出」的路徑,而不是'DirEntry'對象;你沒有使用free/cached'stat'行爲。如果你需要'stat'信息,你可能想複製'scandir.walk'實現並修改它以返回'dirnames'和'filenames'的原始DirEntry對象的'list',而不是返回' 'str'名單'。這是兩全其美的。單次掃描,無重複性統計。或者只是實現專門用於您的用例的自己的遞歸函數。 – ShadowRanger
@ ShadowRanger ..感謝您的澄清。我試圖簡化SO問題的代碼,但認爲我失去了一些意圖。雙重迭代是因爲我試圖避免迭代一些文件夾,我想獲得統計收益率。修改了原來的問題。謝謝! – user2242044