【问题标题】:How to fix FileNotFoundError如何修复 FileNotFoundError
【发布时间】:2023-01-17 07:19:17
【问题描述】:

该函数获取所有文件夹的路径列表并检查它是否为空。如果为空,则删除。但是在她删除文件夹后,出现错误FileNotFoundError: [WinError 3] The system cannot find the path specified: '\\Projects\\Example\\New folder'。我不完全明白为什么删除后要找它。还有一个问题。如果空文件夹内有另一个空文件夹,则只会删除嵌套的文件夹。如何解决?

def delete_empy_folders(paths_to_folders):
    for folder_path in paths_to_folders:
        if not os.listdir(folder_path) and split(folder_path)[-1] not in ignore_list:
            os.rmdir(folder_path)

【问题讨论】:

  • 如果not os.listdir(folder_path) 为真,您的条件将触发。所以你试图删除一个不存在的文件夹。你确定你的条件是正确的吗?看起来您应该在第一个条件中删除 not 并删除一个文件夹(如果它确实存在)。
  • @SembeiNorimaki 这是检查目录是否为空且正确

标签: python file recursion cmd operating-system


【解决方案1】:

问题是您甚至不检查该路径是否存在,并且您无法列出不存在的文件夹的内容。

快速示例:

>>> import os
>>> os.listdir("aaa")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'aaa'

您可以使用 os.path.isdir 检查给定路径是否存在并且是一个目录:

>>> os.path.isdir("/tmp")
True
>>> os.path.isdir("aaa")
False

(不要与 os.path.isfile 混淆 - 你想要目录,ans isfile 检查非目录文件!)

所以你的代码看起来像:

def delete_empy_folders(paths_to_folders):
    for folder_path in paths_to_folders:
        if os.path.isdir(folder_path) and not os.listdir(folder_path) and split(folder_path)[-1] not in ignore_list:
            os.rmdir(folder_path)

Python 还有一个很好的库来处理路径,称为pathlib。如果您决定切换,可能有用的方法的快速演示:

from pathlib import Path
p = Path("/tmp")
p.is_dir() # just like os.path.isdir
p.name # to get only the last name from path, no matter how complex it is, your split(p)[-1]
p.parts # for your own split - for absolute paths first element will be "/", the rest are just stuff between '/'s
p.rmdir() # will only work if empty, just like os.rmdir

在 os/os.path 和 pathlib 中都没有现成的方法来检查目录内的文件。您使用了 os.listdir,对于 pathlib.Path 对象,我们有 iterdir,它是一个生成器(惰性,非常适合目录)——但要具有完全相同的行为,我们可以将其映射到列表:

list(p.iterdir()) # works like os.listdir(p) but returns a list of pathlib.Path objects instead of a list of str

但我们只需要知道是否至少有一个元素,所以让我们使用 next 从生成器中获取一个值——我们将使用第二个参数提供默认值,这样我们就不会得到异常:

next(p.iterdir(), None)

None 是假的(它的if check 表现得像 False/bool(None) 是 False),所以我们要么得到 Path(真)要么 None(假)。

总而言之,

def delete_empy_folders(paths_to_folders):
    for folder_path in paths_to_folders:
        folder_path = Path(folder_path) # if we get strings, but it would be the best to receive Path objects already
        if folder_path.is_dir() and not next(folder_path.iterdir(), None) and p.name not in ignore_list:
            folder_path.rmdir()

【讨论】:

  • 您能否详细说明生成器和“下一个”方法?
  • @Pain Lazy 事物是在您实际从中获取某些东西之前不会对其进行评估的事物。因此,生成器和其他惰性迭代器非常适合迭代大型事物,因为您不必一次存储所有内容,它们会在您需要值时生成(例如,通过使用 for 循环)。这就是为什么我提供了两种列表方法使其等同于 os.listdir,以及如果目录有很多东西时可以节省内存的方法。
  • @Pain 至于next,它是一个从迭代器中获取下一个元素的内置函数。 docs.python.org/3/library/functions.html#next 如果迭代器耗尽(没有更多元素),它将引发 StopIteration 异常。但是如果您提供默认值,它只会返回该值而不是引发异常。 :) | For 循环 for elem in iterable 基本上是在下面做的 - 检查 realpython.com/python-for-loop 的解释
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-15
  • 1970-01-01
  • 1970-01-01
  • 2016-07-04
相关资源
最近更新 更多