发电机不能自尽

时间:2019-09-13 09:19:43

标签: python generator

我正在尝试连接两个功能,一个功能遍历目录并找到文件名,将名称发送给该功能,以检查是否存在30天以上的文件,如果不符合标准则删除该文件。

我尝试使用生成器,并在函数之间建立优雅的“流程”,但是它破坏了for循环和函数,因此需要重新激活该函数。

import os
from datetime import datetime,timedelta

PATH = os.path.abspath(os.path.dirname(__file__)) + '\folder'


def get_dates(p):
    for path, dirs, files in os.walk(p):
        for file in files:
                fullname = path+ '\\'+file
                mtime = os.stat(fullname).st_ctime

                yield (delete_not_needed(fullname, mtime))


def delete_not_needed(fullname, mtime):
    file_time = datetime.fromtimestamp(mtime)
    if datetime.today()-file_time> timedelta(days=30):
        os.remove(fullname)

if __name__ == '__main__':
    next(get_dates(PATH))

我如何才能使这些功能连接起来?

3 个答案:

答案 0 :(得分:2)

您应该返回文件名,然后遍历over生成器以删除这些文件。

def delete_not_needed(fullname, mtime):
    file_time = datetime.fromtimestamp(mtime)
    if datetime.today()-file_time> timedelta(days=30):
        return fullname

if __name__ == '__main__':
    files_to_delete = get_dates(PATH)
    for file in files_to_delete:
        if file:
            os.remove(file)

答案 1 :(得分:1)

您需要循环调用生成器:

for _ in get_dates(PATH):
    pass

这似乎是对发电机的非常不必要的使用,因为它不会产生任何东西。它应该只是在循环中调用delete_not_needed()的普通函数。

答案 2 :(得分:1)

我认为您的代码的总体结构不是最佳的。我建议您尝试用一个简单的句子来解释每个函数/生成器的作用,然后将其放入文档字符串中,并相应地 name 。这将帮助其他人(和您自己)了解您到底想做什么。

在您的原始示例中,get_dates不获取日期,实际上删除了所有不需要的文件,并且不产生任何结果。那么为什么要成为发电机呢?带有循环的标准函数可以解决这个问题(并且您无需手动使用它)。

不过,在这种情况下,生成器可能会有用:生成器采用路径,并且仅生成30天以上的文件名。然后,此生成器的调用者选择如何处理它们(在您的情况下,将其删除)。

import os
from datetime import datetime,timedelta

PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'folder')
DELTA_30_DAYS = timedelta(days=30)

def get_old_files(p, age=DELTA_30_DAYS):
    """
    Yields the fullnames of all files in p older than age
    """
    for path, dirs, files in os.walk(p):
        for file in files:
                fullname = os.path.join(path, file)
                mtime = os.stat(fullname).st_ctime
                file_time = datetime.fromtimestamp(mtime)
                if datetime.today()-file_time> age:
                    yield fullname

if __name__ == '__main__':
    for fullname in get_old_files(PATH):
        os.remove(fullname)

请注意,在“主要”部分的循环中使用了生成器(应如此)。

还请注意age中的可选参数get_old_files,这将使生成器更加灵活。