os.walk / scandir在网络驱动器上运行缓慢

时间:2016-03-01 04:04:57

标签: python python-2.7 batch-file os.walk scandir

我尝试在网络驱动器.xlsm上找到所有O:\个文件(并获取其统计信息),前提是它们不在名为Test的文件夹中。我使用os.walk并切换到scandir.walk,因为它更快。我现在只受网络速度的限制。这段代码似乎在脚本和网络驱动器之间有很多交互。我的代码如下。有没有办法加快速度,可能使用批处理文件?我在Windows上。

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

1 个答案:

答案 0 :(得分:3)

您通过walk隐式地对每个路径进行双重扫描,然后再次明确重新scandir无理由返回path walkwalk已经返回了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代替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
顺便说一句,您可能需要仔细检查是否已为scandir_scandir正确安装/构建了C加速器。如果未构建_scandir,则scandir模块会使用ctypes提供回退实现,但它们会明显变慢,这可以解释性能问题。尝试在交互式Python会话中运行import _scandir;如果它引发ImportError,那么你就没有加速器,所以你正在使用缓慢的后备实现。