我正在寻找一种方法来遍历一个包含数十万个文件的目录。使用 os.listdir
是非常慢的,因为该函数首先从整个指定路径中获取路径列表。
有什么更快的选项吗?
注意:谁曾经对此进行过投票肯定没有面对过这种情况。
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
你在目录中对每个文件做了什么?我认为使用os.listdir并没有真正的选择,但根据你所做的事情,你可能能够并行处理文件。例如,我们可以使用multiprocessing库中的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
本身需要很长时间,因为该目录中的项目数量很多。所以在这种情况下,除非获取到整个列表,否则映射不会启动。 - jdi
ls -U
开始返回结果的速度有多快?由于不需要对文件进行排序,它可以通过子进程管道将它们提供给您。 - John La Rooy