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个使用示例]