【问题标题】:What is the fastest way to check whether a directory is empty in Python在Python中检查目录是否为空的最快方法是什么
【发布时间】:2020-01-17 23:57:16
【问题描述】:

我在 Windows 机器上工作,想检查网络路径上的目录是否为空。

首先想到的是调用os.listdir(),看看它的长度是否为0。

def dir_empty(dir_path):
    return len(os.listdir(dir_path)) == 0

因为这是一个网络路径,我并不总是具有良好的连接性,而且一个文件夹可能包含数千个文件,这是一个非常慢的解决方案。有没有更好的?

【问题讨论】:

标签: python directory path operating-system network-programming


【解决方案1】:

目前我发现的最快的解决方案:

def dir_empty(dir_path):
    return not any((True for _ in os.scandir(dir_path)))

或者,如以下 cmets 中所建议的:

def dir_empty(dir_path):
    return not next(os.scandir(dir_path), None)

在我正在处理的慢速网络上,这需要几秒钟而不是几分钟(os.listdir() 版本需要几分钟)。这似乎更快,因为 any 语句只评估第一个 True 语句。

【讨论】:

  • 这会遍历 dir_path 中的每个文件。而是尝试:return not next(os.scandir(dirpath), None)
  • [True for _ in os.scandir(dir_path)] 在内存中创建一个列表理解,如下所示:[True, True, True, True](每个 scandir 条目一次点击)然后 any 遍历 Trues 列表
  • ups,奇怪的是它实际上提高了我的速度。将调整答案。感谢您指出这一点
【解决方案2】:

从 Python 3.4 开始,您可以使用 pathlib.iterdir() 来生成目录内容的路径对象:

>>> from pathlib import Path
>>>
>>> def dir_empty(dir_path):
...     path = Path(dir_path)
...     has_next = next(path.iterdir(), None)
...     if has_next is None:
...             return True
...     return False

【讨论】:

    【解决方案3】:

    listdir 给出一个列表。 scandir 给出了一个迭代器,它可能会更高效。

    def dir_empty(dir_path):
        try:
            next(os.scandir(dir_path))
            return False
        except StopIteration:
            return True
    

    【讨论】:

      【解决方案4】:

      由于 OP 询问最快的方式,我认为使用 os.scandir 并在我们找到第一个文件后立即返回应该是最快的。 os.scandir 返回一个迭代器。我们应该避免创建一个完整的列表来检查它是否为空。

      测试目录包含大约10万个文件:

      from pathlib import Path    
      import os
      
      path = 'jav/av'
      len(os.listdir(path))
      
      >>> 101204
      

      然后开始我们的测试:

      def check_empty_by_scandir(path):
          with os.scandir(path) as it:
              return not any(it)
          
      def check_empty_by_listdir(path):
          return not os.listdir(path)
      
      def check_empty_by_pathlib(path):
          return not any(Path(path).iterdir())
      
      
      %timeit check_empty_by_scandir(path)
      >>> 179 µs ± 878 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
      
      %timeit check_empty_by_listdir(path)
      >>> 28 ms ± 185 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
      
      %timeit check_empty_by_pathlib(path)
      >>> 27.6 ms ± 140 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
      

      正如我们所见,check_empty_by_listdircheck_empty_by_pathlibcheck_empty_by_scandir 慢大约 155 倍。 os.listdir() 和 Path.iterdir() 的结果是相同的,因为 Path.iterdir() 在后台使用 os.listdir(),在内存中创建一个完整的列表。

      此外,正如人们指出的那样,读取 os.stat 不是一种选择,它在 linux 中的空目录上返回 4096。

      【讨论】:

        【解决方案5】:

        在 Windows 操作系统上有 PathIsDirectoryEmptyA。我们可以用它来检查文件夹是否为空。

        def is_dir_empty(path:str)->bool:
            import ctypes
            shlwapi = ctypes.OleDLL('shlwapi')
            return shlwapi.PathIsDirectoryEmptyA(path.encode('utf-8'))
        

        【讨论】:

          【解决方案6】:

          使用os.stat

          is_empty = os.stat(dir_path).st_size == 0
          

          使用 Python 的pathlib:

          from pathlib import Path
          
          is_empty = Path(dir_path).stat().st_size == 0
          

          【讨论】:

          • 在 Linux 上开箱即用的 ext4 文件系统上,st_size==4096 在空目录上。
          猜你喜欢
          • 2018-11-14
          • 2023-04-03
          • 2011-11-26
          • 2016-08-28
          • 1970-01-01
          • 2020-12-08
          • 2016-07-23
          相关资源
          最近更新 更多