如何创建目录以及任何缺少的父目录?
如何在给定路径创建目录,并沿该路径创建任何缺失的父目录? 例如,Bash 命令 mkdir -p /path/to/nested/directory
可以执行此操作。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
如何在给定路径创建目录,并沿该路径创建任何缺失的父目录? 例如,Bash 命令 mkdir -p /path/to/nested/directory
可以执行此操作。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(27)
在 Python ≥ 3.5 上,使用
pathlib.Path.mkdir
:对于旧版本的 Python,我看到两个质量都很好的答案,每个答案都有一个小缺陷,所以我将给出我的看法:
尝试
os.path.exists
,并考虑os.makedirs
用于创建。正如评论和其他地方所指出的,存在竞争条件 - 如果目录是在 os.path.exists 和 os.makedirs 调用之间创建的,则 os .makedirs 将失败并出现
OSError
。 不幸的是,一揽子捕获 OSError 并继续并不是万无一失的,因为它会忽略由于其他因素(例如权限不足、磁盘已满等)而导致创建目录失败的情况。一种选择是捕获
OSError
并检查嵌入的错误代码(请参阅是否有一种跨平台的方式从 Python 的 OSError 获取信息):或者,可能还有第二个
os.path.exists
,但假设另一个在第一次检查后创建了该目录,然后在第二次检查之前将其删除 - 我们仍然可能被愚弄。根据应用程序的不同,并发操作的危险可能大于或小于其他因素(例如文件权限)造成的危险。 在选择实现之前,开发人员必须更多地了解正在开发的特定应用程序及其预期环境。
现代版本的 Python 通过公开
FileExistsError 极大地改进了此代码
(在 3.3+ 中)......并允许
os.makedirs
的关键字参数称为exist_ok
(在 3.2+ 中)。On Python ≥ 3.5, use
pathlib.Path.mkdir
:For older versions of Python, I see two answers with good qualities, each with a small flaw, so I will give my take on it:
Try
os.path.exists
, and consideros.makedirs
for the creation.As noted in comments and elsewhere, there's a race condition – if the directory is created between the
os.path.exists
and theos.makedirs
calls, theos.makedirs
will fail with anOSError
. Unfortunately, blanket-catchingOSError
and continuing is not foolproof, as it will ignore a failure to create the directory due to other factors, such as insufficient permissions, full disk, etc.One option would be to trap the
OSError
and examine the embedded error code (see Is there a cross-platform way of getting information from Python’s OSError):Alternatively, there could be a second
os.path.exists
, but suppose another created the directory after the first check, then removed it before the second one – we could still be fooled.Depending on the application, the danger of concurrent operations may be more or less than the danger posed by other factors such as file permissions. The developer would have to know more about the particular application being developed and its expected environment before choosing an implementation.
Modern versions of Python improve this code quite a bit, both by exposing
FileExistsError
(in 3.3+)......and by allowing a keyword argument to
os.makedirs
calledexist_ok
(in 3.2+).Python 3.5+:
pathlib.Path.mkdir
< /a> 如上所述,递归地创建目录,如果目录已存在,则不会引发异常。 如果您不需要或不希望创建父级,请跳过parents
参数。Python 3.2+:
使用
pathlib
:如果可以,请安装名为 pathlib 反向移植.org/pypi/pathlib2/" rel="noreferrer">
pathlib2
。 不要安装名为pathlib
的旧版未维护向后移植。 接下来参考上面的Python 3.5+部分,同样使用。如果使用 Python 3.4,即使它带有
pathlib
,它也缺少有用的exist_ok
选项。 向后移植的目的是提供更新且更优秀的 mkdir 实现,其中包括这个缺失的选项。使用
操作系统
:os.makedirs
递归地创建目录,如果目录已经存在,则不会引发异常。 仅当使用 Python 3.2+ 时,它才具有可选的exist_ok
参数,默认值为False
。 这个参数在 Python 2.x 到 2.7 中不存在。 因此,不需要像 Python 2.7 那样进行手动异常处理。Python 2.7+:
使用
pathlib
:如果可以,请安装名为 pathlib 反向移植.org/pypi/pathlib2/" rel="noreferrer">
pathlib2
。 不要安装名为pathlib
的旧版未维护向后移植。 接下来参考上面的Python 3.5+部分,同样使用。使用
os
:虽然简单的解决方案可能首先使用
os.path.isdir
后跟os.makedirs
,上面的解决方案颠倒了顺序两个操作。 这样做可以防止与重复尝试创建目录有关的常见竞争条件,并且还可以消除目录中文件的歧义。请注意,捕获异常并使用
errno
的作用有限,因为会引发OSError: [Errno 17] File isn's
,即errno.EEXIST
对于文件和目录。 简单地检查目录是否存在更可靠。替代方案:
mkpath
创建嵌套目录,如果目录已经存在则不执行任何操作。 这适用于 Python 2 和 3。但请注意distutils< /code>
已被弃用,并计划在 Python 3.12 中删除。
根据 Bug 10948,此替代方案的一个严重限制是它对于给定路径的每个 python 进程只能运行一次。 换句话说,如果您使用它创建一个目录,然后从Python内部或外部删除该目录,然后再次使用
mkpath
重新创建相同的目录,mkpath
将简单地默默地使用先前创建目录的无效缓存信息,并且实际上不会再次创建该目录。 相反,os.makedirs 不依赖于任何此类缓存。 对于某些应用程序来说,此限制可能没问题。关于目录的模式,如果您关心的话请参考文档。
Python 3.5+:
pathlib.Path.mkdir
as used above recursively creates the directory and does not raise an exception if the directory already exists. If you don't need or want the parents to be created, skip theparents
argument.Python 3.2+:
Using
pathlib
:If you can, install the current
pathlib
backport namedpathlib2
. Do not install the older unmaintained backport namedpathlib
. Next, refer to the Python 3.5+ section above and use it the same.If using Python 3.4, even though it comes with
pathlib
, it is missing the usefulexist_ok
option. The backport is intended to offer a newer and superior implementation ofmkdir
which includes this missing option.Using
os
:os.makedirs
as used above recursively creates the directory and does not raise an exception if the directory already exists. It has the optionalexist_ok
argument only if using Python 3.2+, with a default value ofFalse
. This argument does not exist in Python 2.x up to 2.7. As such, there is no need for manual exception handling as with Python 2.7.Python 2.7+:
Using
pathlib
:If you can, install the current
pathlib
backport namedpathlib2
. Do not install the older unmaintained backport namedpathlib
. Next, refer to the Python 3.5+ section above and use it the same.Using
os
:While a naive solution may first use
os.path.isdir
followed byos.makedirs
, the solution above reverses the order of the two operations. In doing so, it prevents a common race condition having to do with a duplicated attempt at creating the directory, and also disambiguates files from directories.Note that capturing the exception and using
errno
is of limited usefulness becauseOSError: [Errno 17] File exists
, i.e.errno.EEXIST
, is raised for both files and directories. It is more reliable simply to check if the directory exists.Alternative:
mkpath
creates the nested directory, and does nothing if the directory already exists. This works in both Python 2 and 3. Note however thatdistutils
has been deprecated, and is scheduled for removal in Python 3.12.Per Bug 10948, a severe limitation of this alternative is that it works only once per python process for a given path. In other words, if you use it to create a directory, then delete the directory from inside or outside Python, then use
mkpath
again to recreate the same directory,mkpath
will simply silently use its invalid cached info of having previously created the directory, and will not actually make the directory again. In contrast,os.makedirs
doesn't rely on any such cache. This limitation may be okay for some applications.With regard to the directory's mode, please refer to the documentation if you care about it.
使用 try except 和 errno 模块中的正确错误代码可以消除竞争条件并且是跨平台的:
换句话说,我们尝试创建目录,但如果它们已经存在,我们将忽略该错误。 另一方面,会报告任何其他错误。 例如,如果您事先创建目录“a”并从中删除所有权限,您将收到一个
OSError
并引发errno.EACCES
(权限被拒绝,错误 13)。Using try except and the right error code from errno module gets rid of the race condition and is cross-platform:
In other words, we try to create the directories, but if they already exist we ignore the error. On the other hand, any other error gets reported. For example, if you create dir 'a' beforehand and remove all permissions from it, you will get an
OSError
raised witherrno.EACCES
(Permission denied, error 13).从 Python 3.5 开始,
pathlib.Path.mkdir
有一个
exist_ok
标志:这会递归地创建目录,如果目录已存在,则不会引发异常。
(就像
os.makedirs
从 python 3.2 开始有一个exist_ok
标志,例如os.makedirs(path, exit_ok=True)
)注意:当我发布此答案时,没有其他答案提到
exist_ok
...Starting from Python 3.5,
pathlib.Path.mkdir
has anexist_ok
flag:This recursively creates the directory and does not raise an exception if the directory already exists.
(just as
os.makedirs
got anexist_ok
flag starting from python 3.2 e.gos.makedirs(path, exist_ok=True)
)Note: when i posted this answer none of the other answers mentioned
exist_ok
...我个人建议您使用 os.path.isdir() 来测试,而不是 os.path.exists() 。
如果您有:
并且有一个愚蠢的用户输入:
...当您将该参数传递给 os.makedirs() 时,您最终会得到一个名为
filename.etc
的目录code> 如果您使用 os.path.exists() 进行测试。I would personally recommend that you use
os.path.isdir()
to test instead ofos.path.exists()
.If you have:
And a foolish user input:
... You're going to end up with a directory named
filename.etc
when you pass that argument toos.makedirs()
if you test withos.path.exists()
.检查
os.makedirs
:(它确保完整路径存在。)要处理目录可能存在的事实,请捕获
OSError
。(如果
exist_ok
为False
(默认值),则如果目标目录已存在,则会引发OSError
。)Check
os.makedirs
: (It makes sure the complete path exists.)To handle the fact the directory might exist, catch
OSError
.(If
exist_ok
isFalse
(the default), anOSError
is raised if the target directory already exists.)尝试
os.path.exists
函数Try the
os.path.exists
function深入了解这种情况的具体情况
您可以在特定路径中提供特定文件,然后从该文件路径中提取目录。 然后,在确保您拥有该目录后,您尝试打开文件进行读取。 要评论此代码:
我们希望避免覆盖内置函数
dir
。 另外,filepath
或者fullfilepath
可能是比filename
更好的语义名称,所以这样写会更好:你的最终目标是打开这个文件,您最初声明,用于编写,但您实际上正在接近此目标(基于您的代码),如下所示,这将打开文件以供阅读:
假设打开以供读取
为什么要为您希望存在并能够读取的文件创建一个目录?
只需尝试打开该文件。
如果目录或文件不存在,您将收到带有关联错误号的
IOError
:无论您的平台如何,errno.ENOENT
都将指向正确的错误号。 如果您愿意,您可以抓住它,例如:假设我们正在开始写作
这可能就是您想要的。
在这种情况下,我们可能不会面临任何竞争条件。 因此,只需照常进行即可,但请注意,对于写入,您需要使用
w
模式打开(或使用a
进行追加)。 使用上下文管理器打开文件也是 Python 最佳实践。然而,假设我们有几个 Python 进程尝试将所有数据放入同一目录中。 那么我们可能会争夺目录的创建。 在这种情况下,最好将 makedirs 调用包装在 try- except 块中。
Insights on the specifics of this situation
You give a particular file at a certain path and you pull the directory from the file path. Then after making sure you have the directory, you attempt to open a file for reading. To comment on this code:
We want to avoid overwriting the builtin function,
dir
. Also,filepath
or perhapsfullfilepath
is probably a better semantic name thanfilename
so this would be better written:Your end goal is to open this file, you initially state, for writing, but you're essentially approaching this goal (based on your code) like this, which opens the file for reading:
Assuming opening for reading
Why would you make a directory for a file that you expect to be there and be able to read?
Just attempt to open the file.
If the directory or file isn't there, you'll get an
IOError
with an associated error number:errno.ENOENT
will point to the correct error number regardless of your platform. You can catch it if you want, for example:Assuming we're opening for writing
This is probably what you're wanting.
In this case, we probably aren't facing any race conditions. So just do as you were, but note that for writing, you need to open with the
w
mode (ora
to append). It's also a Python best practice to use the context manager for opening files.However, say we have several Python processes that attempt to put all their data into the same directory. Then we may have contention over creation of the directory. In that case it's best to wrap the
makedirs
call in a try-except block.我已经写下了以下内容。 但这并不是完全万无一失的。
现在正如我所说,这并不是真正万无一失,因为我们有可能无法创建目录,并且在此期间另一个进程创建它。
I have put the following down. It's not totally foolproof though.
Now as I say, this is not really foolproof, because we have the possiblity of failing to create the directory, and another process creating it during that period.
对此的直接答案是,假设一个简单的情况,您不希望其他用户或进程弄乱您的目录:
或 如果创建目录受到竞争条件的影响(即,如果在检查路径存在后,其他内容可能已经创建了),请执行以下操作:
但也许更好的方法是通过使用临时文件来回避资源争用问题通过
tempfile
:以下是在线文档中的要点:
Python 3.5 中的新功能:
pathlib.Path
和exist_ok
有一个新的
Path
对象(从 3.4 开始),其中包含许多人们想要使用的方法带有路径 - 其中之一是 mkdir。(就上下文而言,我正在使用脚本跟踪我的每周代表。这是脚本中代码的相关部分,使我能够避免每天多次访问 Stack Overflow 以获得相同的数据。)
首先是相关导入:
我们不现在不必处理
os.path.join
- 只需使用/
连接路径部分:然后我幂等地确保目录存在 -
exist_ok 参数出现在 Python 3.5 中:
这是 的相关部分文档:
这是脚本的更多内容 - 就我而言,我不受竞争条件的影响,我只有一个进程期望目录(或包含的文件)在那里,并且我没有任何尝试删除的内容目录。
Path
对象必须先强制转换为str
,然后其他需要str
路径的 API 才能使用它们。也许 Pandas 应该更新为接受抽象基类 os.PathLike 的实例。
The direct answer to this is, assuming a simple situation where you don't expect other users or processes to be messing with your directory:
or if making the directory is subject to race conditions (i.e. if after checking the path exists, something else may have already made it) do this:
But perhaps an even better approach is to sidestep the resource contention issue, by using temporary directories via
tempfile
:Here's the essentials from the online doc:
New in Python 3.5:
pathlib.Path
withexist_ok
There's a new
Path
object (as of 3.4) with lots of methods one would want to use with paths - one of which ismkdir
.(For context, I'm tracking my weekly rep with a script. Here's the relevant parts of code from the script that allow me to avoid hitting Stack Overflow more than once a day for the same data.)
First the relevant imports:
We don't have to deal with
os.path.join
now - just join path parts with a/
:Then I idempotently ensure the directory exists - the
exist_ok
argument shows up in Python 3.5:Here's the relevant part of the documentation:
Here's a little more of the script - in my case, I'm not subject to a race condition, I only have one process that expects the directory (or contained files) to be there, and I don't have anything trying to remove the directory.
Path
objects have to be coerced tostr
before other APIs that expectstr
paths can use them.Perhaps Pandas should be updated to accept instances of the abstract base class,
os.PathLike
.最快最安全的方法是:
如果不存在则创建,如果存在则跳过:
fastest safest way to do it is:
it will create if not exists and skip if exists:
在Python 3.4中,您还可以使用全新的
pathlib
模块:In Python 3.4 you can also use the brand new
pathlib
module:在Python3中,
os.makedirs
支持设置exist_ok
。 默认设置为False
,这意味着如果目标目录已存在,则会引发OSError
。 通过将exist_ok
设置为True
,OSError
(目录存在)将被忽略,并且不会创建该目录。在Python2中,
os.makedirs
不支持设置exist_ok
。 您可以使用 heikki-toivonen 的回答中的方法:In Python3,
os.makedirs
supports settingexist_ok
. The default setting isFalse
, which means anOSError
will be raised if the target directory already exists. By settingexist_ok
toTrue
,OSError
(directory exists) will be ignored and the directory will not be created.In Python2,
os.makedirs
doesn't support settingexist_ok
. You can use the approach in heikki-toivonen's answer:对于单行解决方案,您可以使用 < code>IPython.utils.path.ensure_dir_exists():
来自 文档:确保目录存在。 如果它不存在,请尝试创建它,并在另一个进程执行相同操作时防止竞争条件。
IPython 是一个扩展包,而不是标准库的一部分。
For a one-liner solution, you can use
IPython.utils.path.ensure_dir_exists()
:From the documentation: Ensure that a directory exists. If it doesn’t exist, try to create it and protect against a race condition if another process is doing the same.
IPython is an extension package, not part of the standard library.
相关 Python 文档 建议使用 EAFP 编码风格(请求宽恕比请求许可更容易)。 这意味着该代码
比替代方案更好
文档表明这一点正是因为本问题中讨论的竞争条件。 此外,正如其他人在这里提到的,查询一次而不是两次操作系统具有性能优势。 最后,在某些情况下,当开发人员知道应用程序正在运行的环境时,提出的论点可能支持第二个代码,只能在程序已为其设置了私有环境的特殊情况下得到提倡本身(以及同一程序的其他实例)。
即使在这种情况下,这也是一种不好的做法,并且可能导致长时间无用的调试。 例如,我们为目录设置权限这一事实不应让我们认为印象权限已根据我们的目的进行了适当设置。 可以使用其他权限安装父目录。 一般来说,程序应该始终正确运行,程序员不应该期望一种特定的环境。
The relevant Python documentation suggests the use of the EAFP coding style (Easier to Ask for Forgiveness than Permission). This means that the code
is better than the alternative
The documentation suggests this exactly because of the race condition discussed in this question. In addition, as others mention here, there is a performance advantage in querying once instead of twice the OS. Finally, the argument placed forward, potentially, in favour of the second code in some cases --when the developer knows the environment the application is running-- can only be advocated in the special case that the program has set up a private environment for itself (and other instances of the same program).
Even in that case, this is a bad practice and can lead to long useless debugging. For example, the fact we set the permissions for a directory should not leave us with the impression permissions are set appropriately for our purposes. A parent directory could be mounted with other permissions. In general, a program should always work correctly and the programmer should not expect one specific environment.
您可以将 exit_ok=True 参数传递给 os.makedirs() 函数,以在目录已存在的情况下抑制错误:
You can pass the exist_ok=True parameter to the os.makedirs() function to suppress the error in case the directory already exists:
在我对在 Python 中使用目录时遇到的一些失败和错误感到困惑后,我找到了这个 Q/A。 我正在使用 Python 3(Arch Linux x86_64 系统上的 Anaconda 虚拟环境中的 v.3.5)。
考虑这个目录结构:
这是我的实验/笔记,它提供了说明:
结论:在我看来,“方法 2”更稳健。
[1] 如何安全地创建嵌套目录?
[2] https://docs.python .org/3/library/os.html#os.makedirs
I found this Q/A after I was puzzled by some of the failures and errors I was getting while working with directories in Python. I am working in Python 3 (v.3.5 in an Anaconda virtual environment on an Arch Linux x86_64 system).
Consider this directory structure:
Here are my experiments/notes, which provides clarification:
Conclusion: in my opinion, "Method 2" is more robust.
[1] How can I safely create a nested directory?
[2] https://docs.python.org/3/library/os.html#os.makedirs
您可以使用
mkpath
请注意,它也会创建祖先目录。
它适用于 Python 2 和 3。
You can use
mkpath
Note that it will create the ancestor directories as well.
It works for Python 2 and 3.
如果您将文件写入变量路径,则可以在文件路径上使用它来确保创建父目录。
即使
path_to_file
是file.ext
(零目录深度)也可以工作。请参阅 pathlib.PurePath.parent 和 pathlib.Path.mkdir。
In case you're writing a file to a variable path, you can use this on the file's path to make sure that the parent directories are created.
Works even if
path_to_file
isfile.ext
(zero directories deep).See pathlib.PurePath.parent and pathlib.Path.mkdir.
如果在支持命令的机器上运行,为什么不使用子进程模块
mkdir
带有-p
选项?适用于 python 2.7 和 python 3.6
应该可以在大多数系统上使用。
在可移植性不重要的情况下(例如,使用 docker),解决方案是干净的 2 行。 您也不必添加逻辑来检查目录是否存在。 最后,重新运行是安全的,没有任何副作用
如果您需要错误处理:
Why not use subprocess module if running on a machine that supports command
mkdir
with-p
option ?Works on python 2.7 and python 3.6
Should do the trick on most systems.
In situations where portability doesn't matter (ex, using docker) the solution is a clean 2 lines. You also don't have to add logic to check if directories exist or not. Finally, it is safe to re-run without any side effects
If you need error handling:
您必须在创建目录之前设置完整路径:
这对我有用,希望它也对您有用
You have to set the full path before creating the directory:
This works for me and hopefully, it will works for you as well
我看到了 Heikki Toivonen 和 ABB 的答案和对这种变化的思考。
I saw Heikki Toivonen and A-B-B's answers and thought of this variation.
我使用
os.path.exists()
,这里是一个Python 3脚本,可以用于检查目录是否存在,如果不存在则创建一个目录,如果存在则删除它(如果需要)。它提示用户输入目录并且可以轻松修改。
I use
os.path.exists()
, here is a Python 3 script that can be used to check if a directory exists, create one if it does not exist, and delete it if it does exist (if desired).It prompts users for input of the directory and can be easily modified.
在程序/项目的入口点调用函数
create_dir()
。Call the function
create_dir()
at the entry point of your program/project.使用此命令检查并创建目录
Use this command check and create dir
这可能不能完全回答问题。 但我猜你的真正意图是创建一个文件及其父目录,将其内容全部包含在 1 个命令中。
您可以使用 pathlib 的
fastcore
扩展来实现这一点:path.mk_write(data)
请参阅 fastcore 文档
This may not exactly answer the question. But I guess your real intention is to create a file and its parent directories, given its content all in 1 command.
You can do that with
fastcore
extension to pathlib:path.mk_write(data)
See more in fastcore documentation