是否有一种方法可以从Python内部获得类似于shell上的mkdir -p的功能。我正在寻找一个解决方案,而不是系统调用。我确信代码少于20行,我想知道是否有人已经写了它?


当前回答

最近,我发现这个distutils.dir_util.mkpath:

In [17]: from distutils.dir_util import mkpath

In [18]: mkpath('./foo/bar')
Out[18]: ['foo', 'foo/bar']

其他回答

函数声明;

import os
def mkdir_p(filename):

    try:
        folder=os.path.dirname(filename)  
        if not os.path.exists(folder):  
            os.makedirs(folder)
        return True
    except:
        return False

用法:

filename = "./download/80c16ee665c8/upload/backup/mysql/2014-12-22/adclient_sql_2014-12-22-13-38.sql.gz"

if (mkdir_p(filename):
    print "Created dir :%s" % (os.path.dirname(filename))
import os
from os.path import join as join_paths

def mk_dir_recursive(dir_path):

    if os.path.isdir(dir_path):
        return
    h, t = os.path.split(dir_path)  # head/tail
    if not os.path.isdir(h):
        mk_dir_recursive(h)

    new_path = join_paths(h, t)
    if not os.path.isdir(new_path):
        os.mkdir(new_path)

基于@Dave C的回答,但修复了部分树已经存在的错误

我认为Asa的回答基本上是正确的,但你也可以将其扩展一点,使其更像mkdir -p:

import os

def mkdir_path(path):
    if not os.access(path, os.F_OK):
        os.mkdirs(path)

or

import os
import errno

def mkdir_path(path):
    try:
        os.mkdirs(path)
    except os.error, e:
        if e.errno != errno.EEXIST:
            raise

这两种方法都可以处理路径已经静默存在但会出现其他错误的情况。

我个人已经成功地使用以下方法,但我的函数可能应该被称为“确保此目录存在”:

def mkdirRecursive(dirpath):
    import os
    if os.path.isdir(dirpath): return

    h,t = os.path.split(dirpath) # head/tail
    if not os.path.isdir(h):
        mkdirRecursive(h)

    os.mkdir(join(h,t))
# end mkdirRecursive

正如在其他解决方案中提到的,我们希望能够在模仿mkdir -p的行为时访问文件系统一次。我认为这是不可能的,但我们应该尽可能接近。

先写代码,再解释:

import os
import errno

def mkdir_p(path):
    """ 'mkdir -p' in Python """
    try:
        os.makedirs(path)
    except OSError as exc:  # Python >2.5
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise

正如@tzot回答的注释所指出的那样,在实际创建目录之前检查是否可以创建目录存在问题:您无法判断是否有人同时更改了文件系统。这也符合Python请求原谅的风格,而不是请求许可。

所以我们要做的第一件事就是建立目录,如果出错,找出原因。

正如Jacob Gabrielson指出的那样,我们必须寻找的一种情况是,在我们试图放置目录的地方已经存在一个文件。

使用mkdir -p:

$ touch /tmp/foo
$ mkdir -p /tmp/foo
mkdir: cannot create directory '/tmp/foo': File exists

Python中的类似行为是引发异常。

所以我们要算出是不是这样。不幸的是,我们不能。我们从makedirs得到相同的错误消息,无论目录是否存在(好)或文件是否存在,都将阻止目录的创建(坏)。

弄清楚发生了什么事的唯一方法是再次检查文件系统,看看那里是否有一个目录。如果存在,则静默返回,否则引发异常。

唯一的问题是,文件系统现在的状态可能与调用makedirs时的状态不同。例如:一个文件存在导致makedirs失败,但是现在在它的位置上有一个目录。这其实没有太大关系,因为该函数只会在最后一次文件系统调用目录时静默退出,而不会引发异常。