如何创建目录以及任何缺少的父目录?

发布于 2024-07-09 12:56:17 字数 104 浏览 6 评论 0 原文

如何在给定路径创建目录,并沿该路径创建任何缺失的父目录? 例如,Bash 命令 mkdir -p /path/to/nested/directory 可以执行此操作。

How do I create a directory at a given path, and also create any missing parent directories along that path? For example, the Bash command mkdir -p /path/to/nested/directory does this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(27

俯瞰星空 2024-07-16 12:56:17

在 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

...并允许 os.makedirs 的关键字参数称为 exist_ok(在 3.2+ 中)。

os.makedirs("path/to/directory", exist_ok=True)  # succeeds even if directory exists.

On Python ≥ 3.5, use pathlib.Path.mkdir:

from pathlib import Path
Path("/my/directory").mkdir(parents=True, exist_ok=True)

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 consider os.makedirs for the creation.

import os
if not os.path.exists(directory):
    os.makedirs(directory)

As noted in comments and elsewhere, there's a race condition – if the directory is created between the os.path.exists and the os.makedirs calls, the os.makedirs will fail with an OSError. Unfortunately, blanket-catching OSError 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):

import os, errno

try:
    os.makedirs(directory)
except OSError as e:
    if e.errno != errno.EEXIST:
        raise

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+)...

try:
    os.makedirs("path/to/directory")
except FileExistsError:
    # directory already exists
    pass

...and by allowing a keyword argument to os.makedirs called exist_ok (in 3.2+).

os.makedirs("path/to/directory", exist_ok=True)  # succeeds even if directory exists.
他夏了夏天 2024-07-16 12:56:17

Python 3.5+:

import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) 

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 实现,其中包括这个缺失的选项。

使用操作系统

import os
os.makedirs(path, exist_ok=True)

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

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 isn's,即 errno.EEXIST对于文件和目录。 简单地检查目录是否存在更可靠。

替代方案:

mkpath 创建嵌套目录,如果目录已经存在则不执行任何操作。 这适用于 Python 2 和 3。但请注意 distutils< /code> 已被弃用,并计划在 Python 3.12 中删除。

import distutils.dir_util
distutils.dir_util.mkpath(path)

根据 Bug 10948,此替代方案的一个严重限制是它对于给定路径的每个 python 进程只能运行一次。 换句话说,如果您使用它创建一个目录,然后从Python内部或外部删除该目录,然后再次使用mkpath重新创建相同的目录,mkpath将简单地默默地使用先前创建目录的无效缓存信息,并且实际上不会再次创建该目录。 相反,os.makedirs 不依赖于任何此类缓存。 对于某些应用程序来说,此限制可能没问题。


关于目录的模式,如果您关心的话请参考文档。

Python 3.5+:

import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) 

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 the parents argument.

Python 3.2+:

Using pathlib:

If you can, install the current pathlib backport named pathlib2. Do not install the older unmaintained backport named pathlib. 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 useful exist_ok option. The backport is intended to offer a newer and superior implementation of mkdir which includes this missing option.

Using os:

import os
os.makedirs(path, exist_ok=True)

os.makedirs as used above recursively creates the directory and does not raise an exception if the directory already exists. It has the optional exist_ok argument only if using Python 3.2+, with a default value of False. 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 named pathlib2. Do not install the older unmaintained backport named pathlib. Next, refer to the Python 3.5+ section above and use it the same.

Using os:

import os
try: 
    os.makedirs(path)
except OSError:
    if not os.path.isdir(path):
        raise

While a naive solution may first use os.path.isdir followed by os.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 because OSError: [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 that distutils has been deprecated, and is scheduled for removal in Python 3.12.

import distutils.dir_util
distutils.dir_util.mkpath(path)

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.

天煞孤星 2024-07-16 12:56:17

使用 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”并从中删除所有权限,您将收到一个 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:

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise

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 with errno.EACCES (Permission denied, error 13).

蓬勃野心 2024-07-16 12:56:17

从 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, exit_ok=True))


注意:当我发布此答案时,没有其他答案提到exist_ok...

Starting from Python 3.5, pathlib.Path.mkdir has an exist_ok flag:

from pathlib import Path
path = Path('/my/directory/filename.txt')
path.parent.mkdir(parents=True, exist_ok=True) 
# path.parent ~ os.path.dirname(path)

This recursively creates the directory and does not raise an exception if the directory already exists.

(just as os.makedirs got an exist_ok flag starting from python 3.2 e.g os.makedirs(path, exist_ok=True))


Note: when i posted this answer none of the other answers mentioned exist_ok...

温柔戏命师 2024-07-16 12:56: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

如果您有:

>>> directory = raw_input(":: ")

并且有一个愚蠢的用户输入:

:: /tmp/dirname/filename.etc

...当您将该参数传递给 os.makedirs() 时,您最终会得到一个名为 filename.etc 的目录code> 如果您使用 os.path.exists() 进行测试。

I would personally recommend that you use os.path.isdir() to test instead of 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

If you have:

>>> directory = raw_input(":: ")

And a foolish user input:

:: /tmp/dirname/filename.etc

... You're going to end up with a directory named filename.etc when you pass that argument to os.makedirs() if you test with os.path.exists().

乖乖兔^ω^ 2024-07-16 12:56:17

检查os.makedirs:(它确保完整路径存在。)
要处理目录可能存在的事实,请捕获OSError
(如果 exist_okFalse(默认值),则如果目标目录已存在,则会引发 OSError。)

import os
try:
    os.makedirs('./path/to/somewhere')
except OSError:
    pass

Check os.makedirs: (It makes sure the complete path exists.)
To handle the fact the directory might exist, catch OSError.
(If exist_ok is False (the default), an OSError is raised if the target directory already exists.)

import os
try:
    os.makedirs('./path/to/somewhere')
except OSError:
    pass
空袭的梦i 2024-07-16 12:56:17

尝试 os.path.exists 函数

if not os.path.exists(dir):
    os.mkdir(dir)

Try the os.path.exists function

if not os.path.exists(dir):
    os.mkdir(dir)
涫野音 2024-07-16 12:56:17

深入了解这种情况的具体情况

您可以在特定路径中提供特定文件,然后从该文件路径中提取目录。 然后,在确保您拥有该目录后,您尝试打开文件进行读取。 要评论此代码:

文件名 = "/my/directory/filename.txt" 
  dir = os.path.dirname(文件名) 
  

我们希望避免覆盖内置函数 dir。 另外,filepath或者fullfilepath可能是比filename更好的语义名称,所以这样写会更好:

import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)

你的最终目标是打开这个文件,您最初声明,用于编写,但您实际上正在接近此目标(基于您的代码),如下所示,这将打开文件以供阅读

如果不是 os.path.exists(目录): 
      os.makedirs(目录) 
  f = 文件(文件名) 
  

假设打开以供读取

为什么要为您希望存在并能够读取的文件创建一个目录?

只需尝试打开该文件。

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)

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:

filename = "/my/directory/filename.txt"
dir = os.path.dirname(filename)

We want to avoid overwriting the builtin function, dir. Also, filepath or perhaps fullfilepath is probably a better semantic name than filename so this would be better written:

import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)

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:

if not os.path.exists(directory):
    os.makedirs(directory)
f = file(filename)

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.

with open(filepath) as my_file:
    do_stuff(my_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:

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

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 (or a to append). It's also a Python best practice to use the context manager for opening files.

import os
if not os.path.exists(directory):
    os.makedirs(directory)
with open(filepath, 'w') as my_file:
    do_stuff(my_file)

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.

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)
甜柠檬 2024-07-16 12:56:17

我已经写下了以下内容。 但这并不是完全万无一失的。

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

现在正如我所说,这并不是真正万无一失,因为我们有可能无法创建目录,并且在此期间另一个进程创建它。

I have put the following down. It's not totally foolproof though.

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

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.

千笙结 2024-07-16 12:56:17

检查目录是否存在并在必要时创建它?

对此的直接答案是,假设一个简单的情况,您不希望其他用户或进程弄乱您的目录:

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(后缀='',前缀='tmp',dir=无) 
      用户可调用函数来创建并返回唯一的临时值 
      目录。   返回值是目录的路径名。 

      该目录只能由以下用户可读、可写和搜索 
      创建用户。 

      调用者负责在完成后删除该目录。 
  

Python 3.5 中的新功能:pathlib.Pathexist_ok

有一个新的 Path 对象(从 3.4 开始),其中包含许多人们想要使用的方法带有路径 - 其中之一是 mkdir。

(就上下文而言,我正在使用脚本跟踪我的每周代表。这是脚本中代码的相关部分,使我能够避免每天多次访问 Stack Overflow 以获得相同的数据。)

首先是相关导入:

from pathlib import Path
import tempfile

我们不现在不必处理 os.path.join - 只需使用 / 连接路径部分:

directory = Path(tempfile.gettempdir()) / 'sodata'

然后我幂等地确保目录存在 - exist_ok 参数出现在 Python 3.5 中:

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,然后其他需要 str 路径的 API 才能使用它们。

也许 Pandas 应该更新为接受抽象基类 os.PathLike 的实例。

Check if a directory exists and create it if necessary?

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:

if not os.path.exists(d):
    os.makedirs(d)

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:

import errno
try:
    os.makedirs(d)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise

But perhaps an even better approach is to sidestep the resource contention issue, by using temporary directories via tempfile:

import tempfile

d = tempfile.mkdtemp()

Here's the essentials from the online doc:

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.

New in Python 3.5: pathlib.Path with exist_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 is mkdir.

(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:

from pathlib import Path
import tempfile

We don't have to deal with os.path.join now - just join path parts with a /:

directory = Path(tempfile.gettempdir()) / 'sodata'

Then I idempotently ensure the directory exists - the exist_ok argument shows up in Python 3.5:

directory.mkdir(exist_ok=True)

Here's the relevant part of the documentation:

If exist_ok is true, FileExistsError exceptions will be ignored (same behavior as the POSIX mkdir -p command), but only if the last path component is not an existing non-directory file.

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.

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 objects have to be coerced to str before other APIs that expect str paths can use them.

Perhaps Pandas should be updated to accept instances of the abstract base class, os.PathLike.

穿越时光隧道 2024-07-16 12:56:17

最快最安全的方法是:
如果不存在则创建,如果存在则跳过:

from pathlib import Path
Path("path/with/childs/.../").mkdir(parents=True, exist_ok=True)

fastest safest way to do it is:
it will create if not exists and skip if exists:

from pathlib import Path
Path("path/with/childs/.../").mkdir(parents=True, exist_ok=True)
ぃ弥猫深巷。 2024-07-16 12:56:17
import os
directory = "./out_dir/subdir1/subdir2"
if not os.path.exists(directory):
    os.makedirs(directory)
import os
directory = "./out_dir/subdir1/subdir2"
if not os.path.exists(directory):
    os.makedirs(directory)
青春如此纠结 2024-07-16 12:56:17

在Python 3.4中,您还可以使用全新的pathlib模块

from pathlib import Path
path = Path("/my/directory/filename.txt")
try:
    if not path.parent.exists():
        path.parent.mkdir(parents=True)
except OSError:
    # handle error; you can also catch specific errors like
    # FileExistsError and so on.

In Python 3.4 you can also use the brand new pathlib module:

from pathlib import Path
path = Path("/my/directory/filename.txt")
try:
    if not path.parent.exists():
        path.parent.mkdir(parents=True)
except OSError:
    # handle error; you can also catch specific errors like
    # FileExistsError and so on.
哽咽笑 2024-07-16 12:56:17

Python3中,os.makedirs支持设置exist_ok。 默认设置为False,这意味着如果目标目录已存在,则会引发OSError。 通过将 exist_ok 设置为 TrueOSError(目录存在)将被忽略,并且不会创建该目录。

os.makedirs(path,exist_ok=True)

Python2中,os.makedirs不支持设置exist_ok。 您可以使用 heikki-toivonen 的回答中的方法:

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise

In Python3, os.makedirs supports setting exist_ok. The default setting is False, which means an OSError will be raised if the target directory already exists. By setting exist_ok to True, OSError (directory exists) will be ignored and the directory will not be created.

os.makedirs(path,exist_ok=True)

In Python2, os.makedirs doesn't support setting exist_ok. You can use the approach in heikki-toivonen's answer:

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise
情徒 2024-07-16 12:56:17

对于单行解决方案,您可以使用 < code>IPython.utils.path.ensure_dir_exists()

from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)

来自 文档确保目录存在。 如果它不存在,请尝试创建它,并在另一个进程执行相同操作时防止竞争条件。

IPython 是一个扩展包,而不是标准库的一部分。

For a one-liner solution, you can use IPython.utils.path.ensure_dir_exists():

from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)

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.

白龙吟 2024-07-16 12:56:17

相关 Python 文档 建议使用 EAFP 编码风格(请求宽恕比请求许可更容易)。 这意味着该代码

try:
    os.makedirs(path)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise
    else:
        print "\nBE CAREFUL! Directory %s already exists." % path

比替代方案更好

if not os.path.exists(path):
    os.makedirs(path)
else:
    print "\nBE CAREFUL! Directory %s already exists." % path

文档表明这一点正是因为本问题中讨论的竞争条件。 此外,正如其他人在这里提到的,查询一次而不是两次操作系统具有性能优势。 最后,在某些情况下,当开发人员知道应用程序正在运行的环境时,提出的论点可能支持第二个代码,只能在程序已为其设置了私有环境的特殊情况下得到提倡本身(以及同一程序的其他实例)。

即使在这种情况下,这也是一种不好的做法,并且可能导致长时间无用的调试。 例如,我们为目录设置权限这一事实不应让我们认为印象权限已根据我们的目的进行了适当设置。 可以使用其他权限安装父目录。 一般来说,程序应该始终正确运行,程序员不应该期望一种特定的环境。

The relevant Python documentation suggests the use of the EAFP coding style (Easier to Ask for Forgiveness than Permission). This means that the code

try:
    os.makedirs(path)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise
    else:
        print "\nBE CAREFUL! Directory %s already exists." % path

is better than the alternative

if not os.path.exists(path):
    os.makedirs(path)
else:
    print "\nBE CAREFUL! Directory %s already exists." % path

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.

陈甜 2024-07-16 12:56:17

您可以将 exit_ok=True 参数传递给 os.makedirs() 函数,以在目录已存在的情况下抑制错误:

import os

# Create directory /path/to/nested/directory if it doesn't already exist
os.makedirs('/path/to/nested/directory', exist_ok=True)

You can pass the exist_ok=True parameter to the os.makedirs() function to suppress the error in case the directory already exists:

import os

# Create directory /path/to/nested/directory if it doesn't already exist
os.makedirs('/path/to/nested/directory', exist_ok=True)
路还长,别太狂 2024-07-16 12:56:17

在我对在 Python 中使用目录时遇到的一些失败和错误感到困惑后,我找到了这个 Q/A。 我正在使用 Python 3(Arch Linux x86_64 系统上的 Anaconda 虚拟环境中的 v.3.5)。

考虑这个目录结构:

└── output/         ## dir
   ├── corpus       ## file
   ├── corpus2/     ## dir
   └── subdir/      ## dir

这是我的实验/笔记,它提供了说明:

# ----------------------------------------------------------------------------
# [1] https://stackoverflow.com/questions/273192/how-can-i-create-a-directory-if-it-does-not-exist

import pathlib

""" Notes:
        1.  Include a trailing slash at the end of the directory path
            ("Method 1," below).
        2.  If a subdirectory in your intended path matches an existing file
            with same name, you will get the following error:
            "NotADirectoryError: [Errno 20] Not a directory:" ...
"""
# Uncomment and try each of these "out_dir" paths, singly:

# ----------------------------------------------------------------------------
# METHOD 1:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but no file created (os.makedirs creates dir, not files!  ;-)
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# [2] https://docs.python.org/3/library/os.html#os.makedirs

# Uncomment these to run "Method 1":

#directory = os.path.dirname(out_dir)
#os.makedirs(directory, mode=0o777, exist_ok=True)

# ----------------------------------------------------------------------------
# METHOD 2:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## works
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## works
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but creates a .../doc.txt./ dir
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# Uncomment these to run "Method 2":

#import os, errno
#try:
#       os.makedirs(out_dir)
#except OSError as e:
#       if e.errno != errno.EEXIST:
#               raise
# ----------------------------------------------------------------------------

结论:在我看来,“方法 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:

└── output/         ## dir
   ├── corpus       ## file
   ├── corpus2/     ## dir
   └── subdir/      ## dir

Here are my experiments/notes, which provides clarification:

# ----------------------------------------------------------------------------
# [1] https://stackoverflow.com/questions/273192/how-can-i-create-a-directory-if-it-does-not-exist

import pathlib

""" Notes:
        1.  Include a trailing slash at the end of the directory path
            ("Method 1," below).
        2.  If a subdirectory in your intended path matches an existing file
            with same name, you will get the following error:
            "NotADirectoryError: [Errno 20] Not a directory:" ...
"""
# Uncomment and try each of these "out_dir" paths, singly:

# ----------------------------------------------------------------------------
# METHOD 1:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but no file created (os.makedirs creates dir, not files!  ;-)
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# [2] https://docs.python.org/3/library/os.html#os.makedirs

# Uncomment these to run "Method 1":

#directory = os.path.dirname(out_dir)
#os.makedirs(directory, mode=0o777, exist_ok=True)

# ----------------------------------------------------------------------------
# METHOD 2:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## works
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## works
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but creates a .../doc.txt./ dir
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# Uncomment these to run "Method 2":

#import os, errno
#try:
#       os.makedirs(out_dir)
#except OSError as e:
#       if e.errno != errno.EEXIST:
#               raise
# ----------------------------------------------------------------------------

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

琉璃梦幻 2024-07-16 12:56:17

您可以使用 mkpath

# Create a directory and any missing ancestor directories. 
# If the directory already exists, do nothing.

from distutils.dir_util import mkpath
mkpath("test")    

请注意,它也会创建祖先目录。

它适用于 Python 2 和 3。

You can use mkpath

# Create a directory and any missing ancestor directories. 
# If the directory already exists, do nothing.

from distutils.dir_util import mkpath
mkpath("test")    

Note that it will create the ancestor directories as well.

It works for Python 2 and 3.

故事与诗 2024-07-16 12:56:17

如果您将文件写入变量路径,则可以在文件路径上使用它来确保创​​建父目录。

from pathlib import Path

path_to_file = Path("zero/or/more/directories/file.ext")
parent_directory_of_file = path_to_file.parent
parent_directory_of_file.mkdir(parents=True, exist_ok=True)

即使 path_to_filefile.ext(零目录深度)也可以工作。

请参阅 pathlib.PurePath.parentpathlib.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.

from pathlib import Path

path_to_file = Path("zero/or/more/directories/file.ext")
parent_directory_of_file = path_to_file.parent
parent_directory_of_file.mkdir(parents=True, exist_ok=True)

Works even if path_to_file is file.ext (zero directories deep).

See pathlib.PurePath.parent and pathlib.Path.mkdir.

网白 2024-07-16 12:56:17

如果在支持命令的机器上运行,为什么不使用子进程模块
mkdir 带有 -p 选项?
适用于 python 2.7 和 python 3.6

from subprocess import call
call(['mkdir', '-p', 'path1/path2/path3'])

应该可以在大多数系统上使用。

在可移植性不重要的情况下(例如,使用 docker),解决方案是干净的 2 行。 您也不必添加逻辑来检查目录是否存在。 最后,重新运行是安全的,没有任何副作用

如果您需要错误处理:

from subprocess import check_call
try:
    check_call(['mkdir', '-p', 'path1/path2/path3'])
except:
    handle...

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

from subprocess import call
call(['mkdir', '-p', 'path1/path2/path3'])

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:

from subprocess import check_call
try:
    check_call(['mkdir', '-p', 'path1/path2/path3'])
except:
    handle...
扮仙女 2024-07-16 12:56:17

您必须在创建目录之前设置完整路径:

import os,sys,inspect
import pathlib

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
your_folder = currentdir + "/" + "your_folder"

if not os.path.exists(your_folder):
   pathlib.Path(your_folder).mkdir(parents=True, exist_ok=True)

这对我有用,希望它也对您有用

You have to set the full path before creating the directory:

import os,sys,inspect
import pathlib

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
your_folder = currentdir + "/" + "your_folder"

if not os.path.exists(your_folder):
   pathlib.Path(your_folder).mkdir(parents=True, exist_ok=True)

This works for me and hopefully, it will works for you as well

你对谁都笑 2024-07-16 12:56:17

我看到了 Heikki ToivonenABB 的答案和对这种变化的思考。

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST or not os.path.isdir(path):
            raise

I saw Heikki Toivonen and A-B-B's answers and thought of this variation.

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST or not os.path.isdir(path):
            raise
梦太阳 2024-07-16 12:56:17

我使用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.

吾性傲以野 2024-07-16 12:56:17

在程序/项目的入口点调用函数create_dir()

import os

def create_dir(directory):
    if not os.path.exists(directory):
        print('Creating Directory '+directory)
        os.makedirs(directory)

create_dir('Project directory')

Call the function create_dir() at the entry point of your program/project.

import os

def create_dir(directory):
    if not os.path.exists(directory):
        print('Creating Directory '+directory)
        os.makedirs(directory)

create_dir('Project directory')
清晰传感 2024-07-16 12:56:17

使用此命令检查并创建目录

 if not os.path.isdir(test_img_dir):
     os.mkdir(test_img_dir)

Use this command check and create dir

 if not os.path.isdir(test_img_dir):
     os.mkdir(test_img_dir)
思慕 2024-07-16 12:56:17

这可能不能完全回答问题。 但我猜你的真正意图是创建一个文件及其父目录,将其内容全部包含在 1 个命令中。

您可以使用 pathlib 的 fastcore 扩展来实现这一点:path.mk_write(data)

from fastcore.utils import Path
Path('/dir/to/file.txt').mk_write('Hello World')

请参阅 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)

from fastcore.utils import Path
Path('/dir/to/file.txt').mk_write('Hello World')

See more in fastcore documentation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文