我正在通過包含100,000個文件的目錄尋找到迭代的方法。使用os.listdir
的速度很慢,因爲此函數首先從整個指定路徑獲取路徑列表。遍歷目錄
什麼是最快的選擇?
注意:誰downvoted從來沒有面對這種情況肯定。
我正在通過包含100,000個文件的目錄尋找到迭代的方法。使用os.listdir
的速度很慢,因爲此函數首先從整個指定路徑獲取路徑列表。遍歷目錄
什麼是最快的選擇?
注意:誰downvoted從來沒有面對這種情況肯定。
這另一個問題是在評論爲重複簡稱:
List files in a folder as a stream to begin process immediately
...但我發現的例子是半不工作。這裏是適用於我的固定版本:
from ctypes import CDLL, c_int, c_uint8, c_uint16, c_uint32, c_char, c_char_p, Structure, POINTER
from ctypes.util import find_library
import os
class c_dir(Structure):
pass
class c_dirent(Structure):
_fields_ = [
("d_fileno", c_uint32),
("d_reclen", c_uint16),
("d_type", c_uint8),
("d_namlen", c_uint8),
("d_name", c_char * 4096),
# proper way of getting platform MAX filename size?
# ("d_name", c_char * (os.pathconf('.', 'PC_NAME_MAX')+1))
]
c_dirent_p = POINTER(c_dirent)
c_dir_p = POINTER(c_dir)
c_lib = CDLL(find_library("c"))
opendir = c_lib.opendir
opendir.argtypes = [c_char_p]
opendir.restype = c_dir_p
# FIXME Should probably use readdir_r here
readdir = c_lib.readdir
readdir.argtypes = [c_dir_p]
readdir.restype = c_dirent_p
closedir = c_lib.closedir
closedir.argtypes = [c_dir_p]
closedir.restype = c_int
def listdir(path):
"""
A generator to return the names of files in the directory passed in
"""
dir_p = opendir(".")
try:
while True:
p = readdir(dir_p)
if not p:
break
name = p.contents.d_name
if name not in (".", ".."):
yield name
finally:
closedir(dir_p)
if __name__ == "__main__":
for name in listdir("."):
print name
Works像一個魅力。謝謝! – jldupont
你在做什麼目錄中的每個文件?我認爲使用os.listdir並沒有什麼選擇,但根據你在做什麼,你可能能夠並行處理文件。例如,我們可以使用多處理庫中的Pool來產生更多的Python進程,然後讓每個進程遍歷一小部分文件。
http://docs.python.org/library/multiprocessing.html
這有點粗糙,但我認爲它橫跨得到點...
import sys
import os
from processing import Pool
p = Pool(3)
def work(subsetOfFiles):
for file in subsetOfFiles:
with open(file, 'r') as f:
#read file, do work
return "data"
p.map(work, [[#subSetFiles1],[#subSetFiles2],[#subSetFiles3]])
的總體思路是,以獲得從os.listdir文件的列表,而是逐個超過100,000個文件,我們將100,000個文件分爲20個5000個文件列表,並在每個過程中處理5,000個文件。這種方法的好處之一是它將受益於當前多核系統的趨勢。
我認爲OP的問題在於調用'os.listdir'本身需要很長時間,因爲該目錄中的項目數量很大。所以在這種情況下,地圖不會在整個列表被獲取之前開始。 – jdi
謝謝,我誤解了一些問題。我認爲,即使在這種情況下,你也可以使用我上面概述的方法。您可以讓每個工作進程獲取目錄中文件的相同子集(可能通過直接shell調用),而不是一次獲取所有文件的列表,然後再將其分配給工作進程。我只相信,當我們談論大約10萬個文件時,分而治之是一個好方法,並且由於全局解釋器鎖定,您將通過流程來執行此操作。 – Wulfram
磁盤IO通常不是GIL的問題,所以線程仍然很好,我相信。在系統阻塞呼叫期間,GIL不會被佔用。但即使是分而治之的方法......如何提前將目錄中的文件分開?無論如何,一個目錄列表必須發生,這又是持久性的。你在工作方面所做的事情實際上是第二步。 – jdi
http://stackoverflow.com/questions/120656/directory-listing-in-python – squiguy
[列出文件夾中的文件作爲流立即開始處理](http://stackoverflow.com/questions/4403598/list-files-in-a-folder-as-a-stream-to-begin-process-immediately) – Nemo
@squiguy:你引用的問題與我之後的問題不一樣。 – jldupont