如何在os中使用生成器查找包装器的功能?

时间:2017-12-15 05:26:16

标签: python-3.x recursion generator

我在python中有一个函数,就像find命令一样。所以基本上它会深入到m_depth (maxdepth),如果在ignore_dirs中指定,它将不会进入目录。它将返回walk中找到的文件列表。代码非常简单并使用递归。

但是对于大量文件或更大的深度,递归花费时间并且返回时列表变得越来越大。所以无论如何我都在寻找发生器,所以至少每次迭代的内存消耗都会减少?

我尝试使用yield结果,但只要找到ignore_dirs就会退出。

这是我的代码:

def find(source_d, m_depth, ignore_dirs):
    '''
    This method does a recursive listing of files/directories from a given 
    path upto maximun recursion value provide as m_depth.

    :param source_d: Given source path to start the recursion from
    :param m_depth: Maximum recursion depth [determines how deep the method will traverse through the file system]
    :param ignore_dirs: this paths will not be traversed. List of strings. 
    '''

    def helper_find(path, ignore_dirs, m_depth, curr_depth=1):
        files = []
        if any(ignore_sub_dir == os.path.split(path)[-1] for ignore_sub_dir in ignore_dirs):
            return []

        if m_depth < curr_depth:
            return []

        else:
            things = os.listdir(path)

            for thing in things:
                if(os.path.isdir(os.path.join(path, thing))):
                    files.extend(helper_find(os.path.join(path, thing), ignore_dirs, m_depth, curr_depth+1))

                else:
                    files.append(os.path.join(path, thing))

        return files

    return helper_find(source_d, ignore_dirs, m_depth)

1 个答案:

答案 0 :(得分:2)

答案是肯定的,你可以使用yield from制作一个递归生成器(仅在Python 3中可用):

def find(source_d, m_depth, ignore_dirs):
    '''
    This method does a recursive listing of files/directories from a given
    path upto maximun recursion value provide as m_depth.

    :param source_d: Given source path to start the recursion from
    :param m_depth: Maximum recursion depth [determines how deep the method will traverse through the file system]
    :param ignore_dirs: this paths will not be traversed. List of strings.
    '''
    def helper_find(path, ignore_dirs, m_depth, curr_depth=1):
        if not any(ignore_sub_dir == os.path.split(path)[-1] for ignore_sub_dir in ignore_dirs)and m_depth >= curr_depth:

            things = os.listdir(path)

            for thing in things:
                if(os.path.isdir(os.path.join(path, thing))):
                    yield from helper_find(os.path.join(path, thing), ignore_dirs, m_depth, curr_depth+1)

                else:
                    yield os.path.join(path, thing)

    return helper_find(source_d, ignore_dirs, m_depth)