【发布时间】:2020-09-24 17:48:19
【问题描述】:
我正在尝试编写一个函数,该函数通过遍历下面带有os.walk() 的目录树来查找目录。在我的机器上,这需要 15 秒。
for dir_path, dir_names, filenames in os.walk(os.path.expanduser('~')):
for dir_name in dir_names:
if dir_name == 'some_dir':
path = os.path.join(dir_path, dir_name)
print(path)
我读到os.scandir() 更快,所以我在下面尝试了这个,尽管我认为实现是错误的。它有效,但现在将近 30 秒。
for dir_path, dir_names, filenames in os.walk(os.path.expanduser('~')):
with os.scandir(dir_path) as entries:
for entry in entries:
if entry.name.endswith('some_dir') and entry.is_dir():
print(entry.path)
如何加快速度?
【问题讨论】:
-
os.scandir()需要使用而不是os.walk(),如果您希望它有机会让任何事情变得更快。使用它另外意味着您从操作系统加载名称两次——一次从具有通常性能的os.walk(),另一次从os.scandir()。 -
@CharlesDuffy 据我所知,
os.scandir()是os.listdir()的替代品,因此它返回一个遍历目录元素的迭代器,但不是递归的。所以如果替换os.walk(),它只会返回home文件夹中的元素,而不是子目录中的元素。 -
对,所以你需要多次调用它,每个目录一次被递归到 - 就像
os.walk()在幕后所做的那样。而如果你的 Python 版本有一个os.walk()使用scandir而不是listdir已经开箱即用,那么那里可能没有太多额外的空间。 -
进行完整目录扫描总是很慢——这就是为什么人们通常更喜欢在可行的情况下使用
locate而不是find。find在底层做了很多棘手的低级优化。 -
...如果
some_dir最有可能出现的位置有限,我强烈建议您编写能够意识到这一点的代码并在回退到更广泛的扫描之前优先考虑这些位置(如果不只是要求用户告诉你你需要的资源在哪里,这并不是闻所未闻或罕见的)。