为了账号安全,请及时绑定邮箱和手机立即绑定

如何安全地创建嵌套目录?

如何安全地创建嵌套目录?

忽然笑 2019-06-18 10:01:43
如何安全地创建嵌套目录?检查文件是否将被写入的目录是否存在的最优雅的方法是什么,如果不是,使用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)是否有“打开”的标志,使这种情况自动发生?
查看完整描述

3 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

我看到两个有好品质的答案,每一个都有一个小小的缺陷,所以我会给出我的看法:

试一试os.path.exists,并考虑os.makedirs为了创造。

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

正如注释和其他地方所指出的,存在一个争用条件-如果目录是在os.path.existsos.makedirs呼叫os.makedirs将失败OSError..不幸的是,毛毯OSError而且继续也不是万无一失的,因为它会忽略创建目录的失败,原因是其他因素,如权限不足、磁盘完整等等。

一种选择是将OSError并检查嵌入的错误代码(请参阅有跨平台的方法从Python的OSError获取信息吗?):

import os, errnotry:
    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.makedirsexist_ok(3.2+)。

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


查看完整回答
反对 回复 2019-06-18
?
MM们

TA贡献1886条经验 获得超2个赞

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..接下来,请参阅上面的Python3.5+部分,并使用它。

如果使用Python3.4,即使它附带pathlib,它失去了有用的东西exist_ok选择。Backport的目的是提供一个更新的、更高级的mkdir包括这个缺失的选项。

使用os:

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

os.makedirs如前所述,递归创建目录,如果目录已经存在,则不会引发异常。它有可选的exist_ok参数仅当使用Python3.2+时,默认值为False..这个参数在Python2.x中不存在,最多可达2.7。因此,不需要像Python2.7那样进行手动异常处理。

Python 2.7+:

使用pathlib:

如果可以,安装当前pathlib后端名为pathlib2..不要安装名为pathlib..接下来,请参阅上面的Python3.5+部分,并使用它。

使用os:

import ostry: 
    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不依赖于任何这样的缓存。对于某些应用程序来说,这个限制可能是可以的。


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


查看完整回答
反对 回复 2019-06-18
?
喵喔喔

TA贡献1735条经验 获得超5个赞

使用TRY以外和errno模块中正确的错误代码可以消除争用条件,并且是跨平台的:

import osimport errnodef 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)。


查看完整回答
反对 回复 2019-06-18
  • 3 回答
  • 0 关注
  • 600 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信