os.walk/scandir 网络驱动器速度慢

os.walk/scandir slow on network drive

我试图在网络驱动器 O:\ 上找到所有 .xlsm 文件(并获取它们的统计信息),前提是它们不在名为 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

您正在双重扫描每条路径,一次通过 walk 隐式扫描,然后再次通过显式重新扫描 scandiring path walk return无缘无故地编辑。 walk 已经 return 编辑了 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 代码并将其修改为 return listDirEntry,而不是list 的名字,或者为您的特定需求编写类似的特殊代码;无论哪种方式,这将允许您避免双重扫描,同时保持 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

顺便说一句,您可能需要仔细检查一下您是否正确 installed/built scandir_scandir 的 C 加速器。如果未构建 _scandirscandir 模块会使用 ctypes 提供回退实现,但它们的速度要慢得多,这可以解释性能问题。在交互式 Python 会话中尝试 运行 import _scandir;如果它引发 ImportError,那么你没有加速器,所以你正在使用缓慢的回退实现。