检查文件目录是否存在的最优雅方法是什么,如果不存在,使用 Python 创建目录?这是我尝试过的:
import os
file_path = "/my/directory/filename.txt"
directory = os.path.dirname(file_path)
try:
os.stat(directory)
except:
os.mkdir(directory)
f = file(filename)
不知怎的,我错过了os.path.exists
(感谢 kanja,Blair 和 Douglas)。这就是我现在拥有的:
def ensure_dir(file_path):
directory = os.path.dirname(file_path)
if not os.path.exists(directory):
os.makedirs(directory)
是否有 “开放” 的标志,这会自动发生?
我看到两个具有良好品质的答案,每个答案都有一个小缺陷,所以我会考虑它:
尝试os.path.exists
,并考虑os.makedirs
进行创建。
import os
if not os.path.exists(directory):
os.makedirs(directory)
如注释和其他地方所述,存在竞争条件 - 如果在os.path.exists
和os.makedirs
调用之间创建目录,则os.makedirs
将失败并出现OSError
。不幸的是,全面捕捉OSError
并继续不是万无一失的,因为它会忽略由于其他因素(例如权限不足,完整磁盘等)而无法创建目录。
一种选择是捕获OSError
并检查嵌入的错误代码(请参阅是否存在从 Python 的 OSError 获取信息的跨平台方式 ):
import os, errno
try:
os.makedirs(directory)
except OSError as e:
if e.errno != errno.EEXIST:
raise
或者,可能有第二个os.path.exists
,但假设另一个在第一次检查后创建了目录,然后在第二次检查之前将其删除 - 我们仍然可能被欺骗。
根据应用程序,并发操作的危险可能多于或少于文件权限等其他因素造成的危险。在选择实现之前,开发人员必须更多地了解正在开发的特定应用程序及其预期环境。
import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True)
pathlib.Path.mkdir
所使用的pathlib.Path.mkdir
以递归方式创建目录,并且如果该目录已存在则不会引发异常。如果您不需要或不想创建parents
,请跳过parents
参数。
使用pathlib
:
如果可以,请安装名为pathlib2
的当前pathlib
backport。不要安装名为pathlib
的旧的非维护pathlib
。接下来,请参阅上面的 Python 3.5 + 部分并使用它。
如果使用 Python 3.4,即使它带有pathlib
,它也缺少有用的exist_ok
选项。 backport 旨在提供更新更好的mkdir
实现,其中包括这个缺少的选项。
使用os
:
import os
os.makedirs(path, exist_ok=True)
os.makedirs
使用的os.makedirs
以递归方式创建目录,如果该目录已存在则不会引发异常。它只有在使用 Python 3.2 + 时才有可选的exist_ok
参数,默认值为False
。这个参数在 Python 2.x 中不存在,最高可达 2.7。因此,不需要像 Python 2.7 那样进行手动异常处理。
使用pathlib
:
如果可以,请安装名为pathlib2
的当前pathlib
backport。不要安装名为pathlib
的旧的非维护pathlib
。接下来,请参阅上面的 Python 3.5 + 部分并使用它。
使用os
:
import os
try:
os.makedirs(path)
except OSError:
if not os.path.isdir(path):
raise
虽然天真的解决方案可能首先使用os.path.isdir
然后是os.makedirs
,但上面的解决方案会颠倒两个操作的顺序。这样做可以防止常见的竞争条件与创建目录的重复尝试有关,并且还可以消除目录中的文件歧义。
请注意,捕获异常并使用errno
的用处有限,因为OSError: [Errno 17] File exists
,即errno.EEXIST
,为文件和目录引发。仅检查目录是否存在更可靠。
mkpath
创建嵌套目录,如果该目录已存在mkpath
执行任何操作。这适用于 Python 2 和 3。
import distutils.dir_util
distutils.dir_util.mkpath(path)
根据Bug 10948 ,这种替代方案的一个严重限制是,对于给定路径,每个 python 进程只能运行一次。换句话说,如果你用它来创建一个目录,然后从 Python 内部或外部删除目录,然后再次使用mkpath
重新创建相同的目录, mkpath
将默默地使用其先前创建目录的无效缓存信息,并且实际上不会再次创建目录。相比之下, os.makedirs
并不依赖于任何此类缓存。对于某些应用,此限制可能没问题。
关于目录的模式 ,如果您关心它,请参阅文档。
使用 try 除了和 errno 模块的正确错误代码摆脱了竞争条件并且是跨平台的:
import os
import errno
def make_sure_path_exists(path):
try:
os.makedirs(path)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
换句话说,我们尝试创建目录,但如果它们已经存在,我们会忽略错误。另一方面,报告任何其他错误。例如,如果您事先创建errno.EACCES
' 并从中删除所有权限,则会出现使用errno.EACCES
引发的OSError
(权限被拒绝,错误 13)。