mkdir -p /path/to/nested/directory
可以实现此功能。mkdir -p /path/to/nested/directory
可以实现此功能。在 Python ≥ 3.5 上,使用 pathlib.Path.mkdir
:
from pathlib import Path
Path("/my/directory").mkdir(parents=True, exist_ok=True)
针对较旧版本的Python,我看到两个质量较好但各有小缺陷的答案,因此我将给出我的看法:
尝试使用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的现代版本通过展示FileExistsError
(3.3+中)等方式有效改进了此代码...
try:
os.makedirs("path/to/directory")
except FileExistsError:
# directory already exists
pass
... 并且通过在 3.2+ 版本中允许 一个名为 exist_ok
的关键字参数传递给 os.makedirs
。
os.makedirs("path/to/directory", exist_ok=True) # succeeds even if directory exists.
os.path.exists
也会对文件返回True
。我已发布了一个回答来解决这个问题。 - Asclepiusos.makedirs()
的exists_ok
参数可用于覆盖如何处理路径的先前存在。 - Bobbleos.mkdirs()
可能会创建出意想不到的文件夹。如果使用 os.mkdir()
,这些问题将引发异常并提醒您它们的存在。请注意,涉及文件夹路径时要格外小心。 - drevickoPath("my_directory").mkdir(parents=True, exist_ok=True)
。 - do-meimport pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True)
pathlib.Path.mkdir
递归地创建目录,如果该目录已经存在,则不会引发异常。如果您不需要或希望创建父级目录,请跳过 parents
参数。
使用 pathlib
:
如果可以的话,请安装名为 pathlib2
的当前 pathlib
后端口。不要安装老的未维护的后端口,名为 pathlib
。接下来,请参考上面的 Python 3.5+ 部分并使用相同的方法。
如果使用的是 Python 3.4,即使它带有 pathlib
,也缺少有用的 exist_ok
选项。该后端口旨在提供一个新的和更优秀的 mkdir
实现,其中包括这个缺失的选项。
使用 os
:
import os
os.makedirs(path, exist_ok=True)
os.makedirs
递归地创建目录,如果目录已存在,则不会引发异常。仅当使用 Python 3.2+ 时,它才具有可选参数 exist_ok
,默认值为 False
。在 Python 2.x 中直到 2.7,不存在此参数。因此,无需像使用 Python 2.7 那样进行手动异常处理。
使用 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。但是请注意,distutils
已被弃用,并计划在Python 3.12中删除。import distutils.dir_util
distutils.dir_util.mkpath(path)
根据Bug 10948,这种替代方式的一个严重限制是,对于给定路径,在python进程中仅能使用一次。换句话说,如果您使用它创建一个目录,然后从Python内部或外部删除该目录,然后再次使用mkpath
重新创建相同的目录,则mkpath
将简单地静默地使用其无效的缓存信息,表示先前已经创建了该目录,并且不会实际再次创建该目录。相比之下,os.makedirs
不依赖任何此类缓存。这种限制可能对某些应用程序没关系。 os.path.isdir
之间有其他人删除了该文件夹,则会引发错误,提示该文件夹存在,但实际上是错误的、过时的且容易引起混淆的错误信息。 - farmir使用try except和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
换句话说,我们尝试创建目录,但如果它们已经存在,我们会忽略错误。另一方面,任何其他错误都会报告。例如,如果您事先创建了目录'a'并从中删除了所有权限,则将引发一个具有errno.EACCES
(权限被拒绝,错误13)的OSError
。exception.errno != errno.EEXIST
时引发异常将无意中忽略路径存在但是是非目录对象(如文件)的情况。如果路径是非目录对象,则理想情况下应该引发异常。 - Asclepiusos.makedirs(path,exist_ok=True)
。 - Navin从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
一样,从 Python 3.2 开始,它也有一个exist_ok
标志,例如:os.makedirs(path, exist_ok=True)
)
注意:当我发布这个答案时,其他答案都没有提到 exist_ok
...
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
>>> directory = raw_input(":: ")
还有一个愚蠢的用户输入:
:: /tmp/dirname/filename.etc
如果你将filename.etc
这个参数传递给os.makedirs()
函数,并使用os.path.exists()
函数做测试,最终你会得到一个名为filename.etc
的目录。
检查 os.makedirs
: (它确保完整路径存在。)
为了处理目录可能已经存在的情况,请捕获 OSError
。(如果 exist_ok
是 False
(默认),则会引发一个 OSError
如果目标目录已经存在。)
import os
try:
os.makedirs('./path/to/somewhere')
except OSError:
pass
尝试使用os.path.exists
函数。
if not os.path.exists(dir):
os.mkdir(dir)
os.mkdir
文档:“如果路径中的父目录不存在,则会引发FileNotFoundError
。” - Ryan M你提供了一个特定路径下的文件,并从文件路径中获取目录。然后,在确保你拥有该目录后,尝试打开一个文件进行读取。对于这段代码的评论:
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)
我已经写下了以下内容。但这并非完全可靠。
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
正如我所说的,这并不是绝对可靠的,因为我们有可能在创建目录时失败,并且另一个进程在此期间创建了该目录。
检查目录是否存在并在需要时创建它?
在假设您不希望其他用户或进程干扰您的目录的简单情况下,直接回答是:
if not os.path.exists(d):
os.makedirs(d)
或者如果创建目录会受到竞态条件的影响(即在检查路径是否存在之后,可能已经有其他东西创建了它),请执行以下操作:
import errno
try:
os.makedirs(d)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
但也许一种更好的方法是通过tempfile
使用临时目录来避免资源竞争问题:
import tempfile
d = tempfile.mkdtemp()
以下是在线文档中的要点:
mkdtemp(suffix='', prefix='tmp', dir=None)
User-callable function to create and return a unique temporary
directory. The return value is the pathname of the directory.
The directory is readable, writable, and searchable only by the
creating user.
Caller is responsible for deleting the directory when done with it.
pathlib.Path
带有 exist_ok
Python 3.4引入了一个新的Path
对象,提供许多有关路径操作的方法,其中之一是mkdir
。
(为了背景,我正在使用脚本跟踪我的每周声望值。下面是脚本中相关的代码部分,它使我避免因相同数据每天只能在Stack Overflow上查询一次。)
首先是相关的导入:
from pathlib import Path
import tempfile
现在我们不需要处理 os.path.join
- 只需用 /
来连接路径部分:
directory = Path(tempfile.gettempdir()) / 'sodata'
然后我采用幂等性确保目录存在 - 在Python 3.5中出现了exist_ok
参数:
directory.mkdir(exist_ok=True)
这是文档中相关部分:
如果
exist_ok
为 true,则忽略FileExistsError
异常(与 POSIX 中的mkdir -p
命令相同),但仅当最后一部分路径不是现有的非目录文件时。
这是脚本的更多内容——在我的情况下,我不会受到竞态条件的影响,我只有一个进程期望该目录(或包含的文件)存在,并且我没有任何尝试删除该目录的东西。
todays_file = directory / str(datetime.datetime.utcnow().date())
if todays_file.exists():
logger.info("todays_file exists: " + str(todays_file))
df = pd.read_json(str(todays_file))
Path
对象必须在其它期望 str
路径的 API 使用前转换为 str
。
或许 Pandas 应该更新,接受抽象基类 os.PathLike
的实例。
p
的父目录,这是我的代码片段:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
。 - Thamme Gowda