【问题标题】:How can I improve performance of finding all files in a folder created at a certain date?如何提高在特定日期创建的文件夹中查找所有文件的性能?
【发布时间】:2018-06-12 16:50:45
【问题描述】:

一个文件夹中有 10,000 个文件。 2018 年 6 月 1 日创建的文件很少,2018 年 6 月 9 日创建的文件很少。

我需要找到在 2018 年 6 月 9 日创建的所有文件。但是读取每个文件并获取文件创建日期然后获取 2018-06-09 创建的文件需要很长时间(几乎 2 小时)。

for file in os.scandir(Path):
    if file.is_file():
        file_ctime = datetime.fromtimestamp(os.path.getctime(file)).strftime('%Y- %m- %d %H:%M:%S')
        if file_ctime[0:4] == '2018-06-09':
            # ...  

【问题讨论】:

    标签: python performance scandir


    【解决方案1】:

    您可以尝试使用os.listdir(path) 从给定路径获取所有文件和目录。

    拥有所有文件和目录后,您可以使用 filter 和 lambda 函数创建一个新列表,其中仅包含具有所需时间戳的文件。

    然后您可以遍历该列表以对正确的文件执行所需的工作。

    【讨论】:

      【解决方案2】:

      让我们从最基本的开始 - 为什么要构建 datetime 只是为了将其重新格式化为字符串,然后进行字符串比较?

      那么使用os.scandir() 而不是os.listdir() 的重点是-os.scandir() 返回一个os.DirEntry,它通过os.DirEntry.stat() 调用缓存文件统计信息。

      根据您需要执行的检查,如果您希望对文件名进行大量过滤,os.listdir() 甚至可能会执行得更好,因为您不需要构建整个 os.DirEntry 只是为了丢弃它.

      所以,如果您不希望对名称进行大量过滤,那么为了优化您的循环:

      for entry in os.scandir(Path):
          if entry.is_file() and 1528495200 <= entry.stat().st_ctime < 1528581600:
              pass  # do whatever you need with it
      

      如果你这样做,那么最好坚持os.listdir():

      import stat
      
      for entry in os.listdir(Path):
          # do your filtering on the entry name first...
          path = os.path.join(Path, entry)  # build path to the listed entry...
          stats = os.stat(path)  # cache the file entry statistics
          if stat.S_ISREG(stats.st_mode) and 1528495200 <= stats.st_ctime < 1528581600:
              pass  # do whatever you need with it
      

      如果您想灵活使用时间戳,请预先使用 datetime.datetime.timestamp() 获取 POSIX 时间戳,然后您可以将它们与 stat_result.st_ctime 直接返回的没有转换的结果进行比较。

      但是,即使是您最初的、未优化的方法,对于仅 10k 个条目,也应该比 2 小时快得多。我也会检查底层文件系统,那里似乎有问题。

      【讨论】:

      • 我想将特定日期与文件时间戳进行比较,因此我将文件时间戳重新格式化为变量并与特定日期进行比较。有什么建议可以将特定日期与文件时间戳日期进行比较?
      • @GowthamChinatalacheruvu - 以上是与特定日期(2018-06-09)进行比较,它相当于您的代码。正如我所写,如果您想灵活地使用时间戳,只需从日期构建您自己的时间戳 - 1528495200 是您发出 datetime.datetime(2018, 6, 9).timestamp() 时会得到的,而 1528581600 是发出 @987654349 时会得到的@。将它们存储在变量中(例如min_ts 和max_ts)并在条件中使用它们(即min_ts &lt;= entry.stat().st_ctime &lt; max_ts),您将获得灵活性。
      • 当我使用 stat().st_ctime 时,我们会得到时间戳(日期+时间)。当我将此值与我的特定日期进行比较时,这将失败。从 st_ctime 获取仅日期的任何解决方案?
      • @GowthamChinatalacheruvu - 这就是我使用上述范围(从一个时间戳到另一个时间戳)捕获2018-06-09 的整个日期范围的原因 - 从2018-06-09 00:00:00 到2018-06-09 23:59:59。我不明白为什么您需要将其转换为日期只是为了进行比较?如果您想获得日期,您可以使用datetime.date.fromtimestamp(),但这会不必要地增加您根据您的问题试图避免的代码的执行时间。
      猜你喜欢
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 2023-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多