在 Python 中检查文件或文件夹是否存在的 7 种方法

Python 中文件和目录存在性检查的多种方法

Python 标准库为开发者提供了丰富的工具,以解决各种编程问题。本教程将探讨如何利用内置模块,以多种方式检查文件或目录是否存在。

在命令行界面(CLI)程序中,验证必要的文件或脚本是否位于正确位置至关重要。如果程序执行时缺少指定的文件,可能会导致程序无法正常运行。

本文将介绍几种在 Python 中快速检测文件或文件夹是否存在的技巧。

开始前的准备

在开始以下步骤之前,请确保你的系统已安装 Python 3。打开终端并执行以下命令:

python --version
# 输出示例:Python 3.9.5

如果你的 Python 版本为 2.x,则需要使用 “python3” 命令。如果尚未安装 Python 3,请参考相关的 Python 安装指南。

本教程将使用一些测试文件,请确保创建如下的文件结构:

touch testfile.txt
mkdir testdirectory/ 
touch testdirectory/otherfile.txt

以上命令将创建一个文件 (testfile.txt)、一个目录 (testdirectory) 以及该目录下的另一个文件 (otherfile.txt)。这些文件内容可以为空,因为我们不涉及读取文件内容。

注意:Windows 用户可以使用图形文件管理器创建相同的文件结构。

为了更方便地进行交互式操作,我们推荐使用 Ipython 作为 Python shell。这并非必需,但它可以提供更友好的用户界面。

pip install ipython

安装完成后,只需在终端输入 ipython 即可进入 IPython shell。

现在,我们已完成准备工作,可以深入了解如何在 Python 中检查文件或文件夹的存在性。

利用 try-except 语句处理文件打开异常

这是一种直接的方法。尝试打开一个不存在的文件时,Python 会抛出一个 FileNotFoundError 异常。

In [1]: open('im-not-here.txt')
---------------------------------------------------------------------------
FileNotFoundError: [Errno 2] No such file or directory: 'im-not-here.txt'

我们可以利用这一点,通过捕获异常来判断文件是否存在。

In [2]: try:
   ...:     file = open('im-not-here.txt')
   ...:     print(file) # 文件句柄
   ...:     file.close()
   ...: except FileNotFoundError:
   ...:     print('抱歉,要查找的文件不存在')
   ...:     exit()
   ...: 
抱歉,要查找的文件不存在

上述代码中,如果文件不存在,程序会打印自定义消息并停止执行。

请注意,`exit()` 函数仅在捕获到 `FileNotFoundError` 异常时才会执行。接下来,我们看看如果文件确实存在会发生什么:

In [2]: try:
   ...:     file = open('testfile.txt')
   ...:     print(file) # 文件句柄
   ...:     file.close()
   ...: except FileNotFoundError:
   ...:     print('抱歉,要查找的文件不存在')
   ...:     exit()
   ...: 
<_io.TextIOWrapper name="testfile.txt" mode="r" encoding='UTF-8'>

注意,我们在打开文件后立即将其关闭。根据 Python 文档

在不使用 `with` 关键字或调用 `file.close()` 的情况下直接调用 `file.write()` 可能导致写入操作无法完全写入磁盘,即使程序成功退出。

即使我们不写入文件,也强烈建议关闭文件,这有助于避免 性能问题

如果不想手动关闭文件,可以使用 `with` 上下文管理器,它可以自动分配和释放资源,因此我们无需显式关闭文件。

In [3]: try:
   ...:     with open('testfile.txt') as file:
   ...:         print(file)
   ...:         # 不需要关闭文件
   ...: except FileNotFoundError:
   ...:     print('抱歉,要查找的文件不存在')
   ...:     exit()
   ...: 
   ...: 
<_io.TextIOWrapper name="testfile.txt" mode="r" encoding='UTF-8'>

这种方法在写入文件时非常有用,但如果仅仅是为了检查文件是否存在,其效率较低。接下来,我们将介绍其他方法。

使用 os.path.exists()

os 模块提供了多种与操作系统交互的函数。我们可以使用 `os.path.exists()` 函数来检查文件或文件夹是否存在。该函数接收文件或目录的路径作为参数,并根据路径是否存在返回布尔值。

注意:路径是文件或目录在文件系统中的唯一标识。

在 Python 中,os.path 子模块包含专门用于处理文件路径的函数。所有这些函数都接受字符串或字节形式的路径参数。你可以使用绝对路径,例如:

/home/daniel/.bashrc

也可以使用相对路径,这取决于你运行脚本的目录:

.bashrc
# 在我的 home 目录下运行脚本

以下是 `os.path.exists()` 函数的示例,在我的测试文件所在的目录下运行:

In [1]: import os

In [2]: os.path.exists('testfile.txt')
Out[2]: True

In [3]: os.path.exists('testdirectory')
Out[3]: True

In [4]: os.path.exists('hey-i-dont-exist')
Out[4]: False

如你所见,当文件或目录存在时,函数返回 `True`,否则返回 `False`。

使用 os.path.isfile()

如果只想确认文件的存在,而非目录,可以使用 `os.path.isfile()` 函数。

In [1]: import os

In [2]: os.path.isfile('testfile.txt')
Out[2]: True

In [3]: os.path.isfile('testdirectory/')
Out[3]: False

In [4]: os.path.isfile('i-dont-even-exist')
Out[4]: False

In [5]: os.path.isfile('testdirectory/otherfile.txt')
Out[5]: True

注意:在 Unix 系统中,目录通常以正斜杠 (/) 结尾,而在 Windows 中使用反斜杠 ()。

上述代码中,`isfile()` 函数返回两次 `False`,原因如下:

  • ‘testdirectory/’ 是一个目录,因此不被视为文件。虽然在 Linux 中 一切皆文件,但 Python 为了方便起见,将目录作为不同的类型对待(如果你尝试打开一个目录,你会得到一个 `IsADirectoryError` 异常)。
  • ‘i-dont-even-exist’ 指向一个不存在的文件。

使用 os.path.isdir()

如果想检查目录是否存在,可以使用 `os.path.isdir()` 函数。如果给定的路径指向目录,该函数返回 `True`。

In [1]: import os

In [2]: os.path.isdir('testfile.txt')
Out[2]: False

In [3]: os.path.isdir('testdirectory')
Out[3]: True

In [4]: os.path.isdir('anotherfile.txt')
Out[4]: False

注意,即使路径指向的是一个存在的文件,上面的示例也会返回 `False`。

使用 glob 模块

glob 模块提供了可以使用 类 Unix shell 模式的功能(因此,它可能在 Windows 上无法正常工作)。要检查当前目录中是否存在与模式匹配的文件,可以使用 `glob.glob()` 函数。

In [1]: import glob

In [2]: glob.glob('testfile.txt')
Out[2]: ['testfile.txt']

In [3]: glob.glob('testdirectory')
Out[3]: ['testdirectory']

在上述代码中,传递给 `glob` 函数的模式是一个字符串,表示测试文件和目录的路径。由于两条路径都存在,函数返回一个包含匹配路径名的列表。

注意:如果模式不匹配,将会返回一个空列表。

考虑到 `glob` 函数支持模式匹配,我们不妨看看它的一些主要优势:

以下代码获取所有扩展名为 .txt 和 .py 的文件路径:

In [4]: glob.glob('*.txt')
Out[4]: ['testfile.txt']

In [5]: glob.glob('*.py')
Out[5]: 
['pathlib-exists.py',
 'list-dir.py',
 'glob-file.py',
 'open-except.py',
 'subprocess-test.py',
 'isfile.py',
 'exists.py',
 'isdir.py']

使用 pathlib 模块

pathlib 模块 是处理路径的最佳方式之一,它提供了一个简洁的接口,将文件路径作为对象处理。

更重要的是,`Path` 实例包含所有获取特定路径信息的方法,包括与先前选项类似的功能。

注意:需要 Python 3.4 或更高版本才能使用 `pathlib` 库。

您可以使用的 `Path` 方法如下:

检查路径是否存在

In [1]: from pathlib import Path

In [2]: Path('testfile.txt').exists()
Out[2]: True

In [3]: Path('im-not-here.txt').exists()
Out[3]: False

In [4]: Path('testdirectory').exists()
Out[4]: True

与 `os.path.exists()` 相同。

检查路径是否指向文件

In [5]: Path('testfile.txt').is_file()
Out[5]: True

In [6]: Path('testdirectory').is_file()
Out[6]: False

等同于 `os.path.isfile()`。

检查路径是否指向目录

In [7]: Path('testfile.txt').is_dir()
Out[7]: False

In [8]: Path('testdirectory').is_dir()
Out[8]: True

对应于 `os.path.isdir()`。

使用 subprocess 模块

如果您是 `subprocess` 模块的爱好者,那么应该了解此选项。可以使用 test 命令.

注意:`test` 命令仅适用于 Unix 系统。

以下测试标志可以完成工作:

  • `test -e`:检查路径是否存在
  • `test -f`:检查文件是否存在
  • `test -d`:检查文件夹是否存在

如果想了解更多 `test` 命令标志,可以通过运行以下命令阅读手册:

man test

使用 `subprocess` 检查路径:

以下代码通过比较子进程的返回码是否为 0 来确定路径是否存在。

记住,在 Linux 中,如果进程运行成功,它将返回 0;否则,将返回其他代码。

In [1]: from subprocess import run

In [2]: run(['test', '-e', 'testfile.txt']).returncode == 0
Out[2]: True

In [3]: run(['test', '-e', 'im-not-here.txt']).returncode == 0
Out[3]: False

在第一条语句中,我们导入了 `subprocess` 模块,然后使用 `run` 函数 并获取其返回码。

使用 `subprocess` 验证文件是否存在

In [4]: run(['test', '-f', 'testfile.txt']).returncode == 0
Out[4]: True

In [5]: run(['test', '-f', 'testdirectory']).returncode == 0
Out[5]: False

使用 `subprocess` 检查目录:

In [6]: run(['test', '-d', 'testfile.txt']).returncode == 0
Out[6]: False

In [7]: run(['test', '-d', 'testdirectory']).returncode == 0
Out[7]: True

不建议使用此选项,因为它会消耗更多资源,且没有额外的优势。

总结

Python 是最常用的编程语言之一,它可以通过与操作系统交互来实现流程自动化。其中一个非常有用的功能是检查文件或文件夹是否存在。

最直接的方法是:

  • 直接打开文件并处理异常。
  • 使用 `os.path` 或 `pathlib` 模块的 `exists()` 函数。

本教程中,你学习了:

  • 如何打开文件并处理 `FileNotFoundError` 异常
  • 路径的概念
  • `os.path` 子模块提供了 3 个不同的函数来检查文件或文件夹是否存在
  • Unix 系统使用正斜杠 (/),而 Windows 系统使用反斜杠 ()

接下来阅读:什么是 Python 中的子进程? [5个使用示例]