【问题标题】:Read files in a directory starting by a specific date using python使用python读取从特定日期开始的目录中的文件
【发布时间】:2021-04-19 01:01:54
【问题描述】:

我有一个自动化流程,需要对文件执行一些操作。另一个进程创建这些文件并将它们存储在一个目录中,我只需要处理最近的文件,但必须将这些文件留在其中并且永远不要删除它们,因为我认为该进程开始使用大量文件获得所需文件时的资源。

我最初的想法是创建另一个进程,将最近的文件(为了确保额外的一天)复制到另一个文件夹,但我只是想知道(或者我确定呵呵)​​是否有更好的方法来获取这些文件文件而不阅读所有文件,或者我的代码是否可以优化。

我的主要问题是,当我进入这部分代码时,服务器的 CPU 使用率正在获取图表,我假设在某些时候该进程会由于某些操作系统错误而中断。我只需要获取所需文件的名称,这些文件的创建日期大于我使用的最后一个文件,每次我对文件执行操作时,该名称都会转到数据库中的表中我得到最后一个文件的名称。我的问题不在于查询或执行的操作,它是最低的 CPU 使用率,只是这部分我读取所有文件并比较它们的日期并将它们添加到数组中。

这是我的代码(如果它很可怕不要生气)重载在 for 之后开始:

def get_ordered_files():
    valid_files = []
    epoch = datetime.datetime.utcfromtimestamp(0)
    get_last_file = check_last_successful_file()
    last_date = os.path.getctime(get_last_file)
    files = glob.glob(files_location + file_extension)
    files.sort(key=os.path.getctime, reverse=False)
    for single_file in files:
        total_days_file = datetime.datetime.fromtimestamp(os.path.getctime(single_file)) - epoch
        total_days_last = datetime.datetime.fromtimestamp(last_date) - epoch
        if total_days_file.total_seconds() > total_days_last.total_seconds():
            check_empty = get_email_account(single_file)
            if check_empty != "" and check_empty is not None:
                valid_files.append(single_file)
    return valid_files

非常感谢您的所有帮助(我使用的是 python 3.8)。

【问题讨论】:

  • 人们不会对你的代码生气,但你可能会得到一些关于你的问题的反馈——不清楚你打算对这些文件执行什么“操作”。您打算更改文件吗?如果这改变了他们的文件日期可以吗(这样他们可能会再次被捡起)?我们讨论了多少文件,需要多久运行一次?
  • 感谢@Grismar,我在我的问题中添加了更多信息。文件保持不变,只需读取它们即可完成操作。

标签: python python-3.x


【解决方案1】:

您的代码中有很多冗余操作。

例如,在循环内使用fromtimestamp() 计算total_days_last 可以简单地在循环外完成一次。事实上,datetime 函数的使用和epoch 的使用似乎是不必要的,因为您可以直接比较文件ctime 的值。

os.path.getctime() 在每个文件上被调用两次:一次用于排序,第二次用于计算total_days_file

这些对大量文件的重复计算将成为性能问题的一部分。

另一个问题是,如果有大量文件,files 列表可能会变得非常大并且需要大量内存。

if check_empty != "" and check_empty is not None: 可以简单地写成if check_empty:

这是一个简化版:

def get_ordered_files():
    last_ctime = os.path.getctime(check_last_successful_file())
    files = glob.glob(files_location + file_extension)
    files.sort(key=os.path.getctime)
    return [f for f in files
                if os.path.getctime(f) > last_ctime and get_email_account(f)]

这消除了大部分冗余代码,但仍为每个文件调用两次os.path.getctime()。为了避免这种情况,我们可以在第一次获得每个文件时存储ctime

pattern = os.path.join(files_location, file_extension)

def get_ordered_files():
    last_ctime = os.path.getctime(check_last_successful_file())
    files = ((filename, ctime) for filename in glob.iglob(pattern)
                if (ctime := os.path.getctime(filename)) > last_ctime and
                    get_email_account(filename))
    return (filename for filename, _ in sorted(files, key=itemgetter(1)))

这里将生成器表达式分配给files。它使用glob.iglob(),它是glob.glob() 的迭代器版本,它不会一次存储所有文件。文件名及其 ctime 值都存储为元组。生成器表达式过滤掉太旧的文件和没有关联电子邮件帐户的文件。最后返回另一个生成器,按 ctime 对文件进行排序。然后调用代码可以遍历生成器,或在其上调用list() 以将其实现为列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-11
    • 2019-12-03
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多