pyton-如何创建一个不存在的目录?

检查文件将要写入的目录是否存在最优雅的方法是什么,如果不是,使用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,布莱尔和道格拉斯)。这是我现在拥有的:

def ensure_dir(file_path):
    directory = os.path.dirname(file_path)
    if not os.path.exists(directory):
        os.makedirs(directory)

有没有“开放”的标志,这会自动发生?

答案


我看到两个质量很好的答案,每个答案都有一个小缺陷,所以我会考虑一下:

尝试os.path.exists,并考虑os.makedirs创造。

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

正如评论和其他地方所指出的那样,竞争条件 – 如果目录是在创建os.path.existsos.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 3.5+:

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

pathlib.Path.mkdir如上面所使用的那样递归地创建目录,并且如果该目录已经存在则不会引发异常。如果您不需要或不想创建父母,请跳过该parents论点。

Python 3.2+:

使用pathlib

如果可以,请安装指定的当前pathlibbackport pathlib2。不要安装旧的未维护的backport pathlib。接下来,请参阅上面的Python 3.5+部分并使用它。

如果使用Python 3.4,即使它附带了pathlib,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

如果可以,请安装指定的当前pathlibbackport pathlib2。不要安装旧的未维护的backport 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 existserrno.EEXIST针对文件和目录引发异常。简单地检查目录是否存在更为可靠。

替代方案:

mkpath创建嵌套目录,如果该目录已经存在,则不执行任何操作。这适用于Python 2和Python 3。

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

根据Bug 10948,这种替代方案的一个严重限制是它对于给定的路径在每个Python进程中仅工作一次。换句话说,如果你使用它来创建一个目录,那么从Python内部或外部删除目录,然后mkpath再次使用来重新创建相同的目录,mkpath将简单地静静地使用其以前创建目录的无效缓存信息,而不会实际上再次制作目录。相比之下,os.makedirs不依赖于任何这样的缓存。对于某些应用程序,此限制可能没有问题。


使用除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(Permission denied,错误13)的引发。


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

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

洞察这种情况的具体情况

你在特定的路径下给出一个特定的文件,然后从文件路径中取出目录。然后,确保您有目录后,您尝试打开一个文件进行阅读。对此代码发表评论:

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)

添加评论

友情链接:蝴蝶教程