问题 如何在Python中安全地创建嵌套目录?
检查文件目录是否存在的最优雅方法是什么,如果不存在,使用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)
是否有“开放”的标志,这会自动发生?
3112
2017-11-07 18:56
起源
答案:
我看到两个具有良好品质的答案,每个答案都有一个小缺陷,所以我会考虑它:
尝试 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
,但假设另一个人在第一次检查后创建了目录,然后在第二次检查之前将其删除 - 我们仍然可以被愚弄。
根据应用程序,并发操作的危险可能多于或少于文件权限等其他因素造成的危险。在选择实现之前,开发人员必须更多地了解正在开发的特定应用程序及其预期环境。
3691
2017-11-07 19:06
Python 3.5+:
import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True)
pathlib.Path.mkdir
如上所用,递归创建目录,如果目录已存在则不引发异常。如果您不需要或希望创建父项,请跳过 parents
论据。
Python 3.2+:
运用 pathlib
:
如果可以,请安装当前的 pathlib
后端命名 pathlib2
。不要安装名为的旧的非维护后端口 pathlib
。接下来,请参阅上面的Python 3.5+部分并使用它。
如果使用Python 3.4,即使它附带 pathlib
,它缺少有用的 exist_ok
选项。 backport旨在提供更新更好的实现 mkdir
其中包括这个缺失的选项。
运用 os
:
import os
os.makedirs(path, exist_ok=True)
os.makedirs
如上所用,递归创建目录,如果目录已存在则不引发异常。它有可选的 exist_ok
参数仅在使用Python 3.2+时,默认值为 False
。这个参数在Python 2.x中不存在,最高可达2.7。因此,不需要像Python 2.7那样进行手动异常处理。
Python 2.7+:
运用 pathlib
:
如果可以,请安装当前的 pathlib
后端命名 pathlib2
。不要安装名为的旧的非维护后端口 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
创建嵌套目录,如果该目录已存在则不执行任何操作。这适用于Python 2和3。
import distutils.dir_util
distutils.dir_util.mkpath(path)
每 错误10948,这个替代方案的一个严重限制是它对于给定路径每个python进程只能工作一次。换句话说,如果您使用它来创建目录,那么从Python内部或外部删除目录,然后使用 mkpath
再次重新创建相同的目录, mkpath
将只是默默地使用其先前创建目录的无效缓存信息,并且实际上不会再次创建目录。相反, os.makedirs
不依赖于任何此类缓存。对于某些应用,此限制可能没问题。
关于目录的 模式如果您关心它,请参阅文档。
815
2018-01-16 17:31
使用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
换句话说,我们尝试创建目录,但如果它们已经存在,我们会忽略错误。另一方面,报告任何其他错误。例如,如果您事先创建了dir'a'并从中删除了所有权限,那么您将得到一个 OSError
提出来 errno.EACCES
(许可被拒绝,错误13)。
573
2018-02-17 17:17
我个人建议你使用 os.path.isdir()
测试而不是 os.path.exists()
。
>>> os.path.exists('/tmp/dirname')
True
>>> os.path.exists('/tmp/dirname/filename.etc')
True
>>> os.path.isdir('/tmp/dirname/filename.etc')
False
>>> os.path.isdir('/tmp/fakedirname')
False
如果你有:
>>> dir = raw_input(":: ")
一个愚蠢的用户输入:
:: /tmp/dirname/filename.etc
...你最终会得到一个名为的目录 filename.etc
当你传递那个参数时 os.makedirs()
如果你测试 os.path.exists()
。
85
2018-01-14 17:57
检查 os.makedirs:(确保存在完整路径。)
要处理目录可能存在的事实,请捕获OSError。
(如果exist_ok为False(默认值),则在目标目录已存在的情况下引发OSError。)
import os
try:
os.makedirs('./path/to/somewhere')
except OSError:
pass
56
2017-11-07 19:01
洞察这种情况的具体情况
您在特定路径中提供特定文件,然后从文件路径中提取目录。然后在确保您拥有该目录后,尝试打开文件进行读取。要评论此代码:
filename = "/my/directory/filename.txt"
dir = os.path.dirname(filename)
我们想避免覆盖内置函数, dir
。也, filepath
也许 fullfilepath
可能是比语言更好的语义名称 filename
所以写得更好:
import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)
你的最终目标是打开这个文件,你最初说,写,但你实际上是接近这个目标(基于你的代码),这样打开文件 读:
if not os.path.exists(directory):
os.makedirs(directory)
f = file(filename)
假设开放阅读
为什么要为您希望在那里并且能够阅读的文件创建一个目录?
只是尝试打开文件。
with open(filepath) as my_file:
do_stuff(my_file)
如果目录或文件不在那里,你会得到一个 IOError
带有相关的错误号: errno.ENOENT
无论您的平台如何,都将指向正确的错误编号。如果你愿意,你可以抓住它,例如:
import errno
try:
with open(filepath) as my_file:
do_stuff(my_file)
except IOError as error:
if error.errno == errno.ENOENT:
print 'ignoring error because directory or file is not there'
else:
raise
假设我们正在写作
这是 大概 你想要什么。
在这种情况下,我们可能没有遇到任何竞争条件。所以就像你一样,但请注意,对于写作,你需要打开 w
模式(或 a
附加)。使用上下文管理器打开文件也是Python的最佳实践。
import os
if not os.path.exists(directory):
os.makedirs(directory)
with open(filepath, 'w') as my_file:
do_stuff(my_file)
但是,假设我们有几个Python进程试图将所有数据放入同一目录中。然后我们可能会争论创建目录。在这种情况下,最好包装 makedirs
在try-except块中调用。
import os
import errno
if not os.path.exists(directory):
try:
os.makedirs(directory)
except OSError as error:
if error.errno != errno.EEXIST:
raise
with open(filepath, 'w') as my_file:
do_stuff(my_file)
29
2018-01-22 23:49
从Python 3.5开始, pathlib.Path.mkdir
有一个 exist_ok
旗:
from pathlib import Path
path = Path('/my/directory/filename.txt')
path.parent.mkdir(parents=True, exist_ok=True)
# path.parent ~ os.path.dirname(path)
这会以递归方式创建目录,如果目录已存在,则不会引发异常。
(就像 os.makedirs
得到了 exists_ok
标志从python 3.2)开始。
28
2017-12-14 16:06
我已经放下了以下内容。但这并非完全万无一失。
import os
dirname = 'create/me'
try:
os.makedirs(dirname)
except OSError:
if os.path.exists(dirname):
# We are nearly safe
pass
else:
# There was an error on creation, so make sure we know about it
raise
现在正如我所说,这并非万无一失,因为我们有可能无法创建目录,而另一个进程在此期间创建它。
22
2017-11-07 21:23
试试吧 os.path.exists
功能
if not os.path.exists(dir):
os.mkdir(dir)
22
2017-11-07 19:00