如何创建一个不存在的目录?
检查文件将要写入的目录是否存在最优雅的方法是什么,如果不是,使用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
,但假设另一个在第一次检查后创建目录,然后在第二个之前删除它 - 我们仍然可能被愚弄。
根据应用程序的不同,并发操作的危险可能比其他因素(如文件权限)带来的危险更大或更小。 在选择实现之前,开发人员必须更多地了解正在开发的特定应用程序及其预期环境。
Python 3.5+:
import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True)
pathlib.Path.mkdir
使用的pathlib.Path.mkdir
递归创建目录,如果目录已经存在,则不会引发异常。 如果您不需要或不想要创建parents
,请跳过parents
说法。
Python 3.2+:
使用pathlib
:
如果可以,请安装名为pathlib2
的当前pathlib
backport。 不要安装名为pathlib
的旧的未保持的backport。 接下来,请参阅上面的Python 3.5+部分并使用它。
如果使用Python 3.4,即使它带有pathlib
,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一样,不需要手动异常处理。
Python 2.7+:
使用pathlib
:
如果可以,请安装名为pathlib2
的当前pathlib
backport。 不要安装名为pathlib
的旧的未保持的backport。 接下来,请参阅上面的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和Python 3。
import distutils.dir_util
distutils.dir_util.mkpath(path)
根据Bug 10948,这种替代方案的一个严重限制是它对于给定的路径在每个Python进程中仅工作一次。 换句话说,如果你用它创建一个目录,然后从Python内部或外部删除目录,然后再次使用mkpath
重新创建相同的目录, mkpath
将简单地静静地使用它以前创建目录的无效缓存信息,以及实际上不会再次制作目录。 相比之下, os.makedirs
不依赖任何这样的缓存。 对于某些应用程序,此限制可能没有问题。
关于目录的模式,如果您关心它,请参阅文档。
使用除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
(Permission denied,error 13)引发的OSError
。