Python中的mkdir -pfunction

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

mkdir -pfunction如下:

 import errno import os def mkdir_p(path): try: os.makedirs(path) except OSError as exc: # Python >2.5 if exc.errno == errno.EEXIST and os.path.isdir(path): pass else: raise 

更新

对于os.makedirsos.makedirs具有可选的第三个参数 exist_ok ,如果为true,则启用mkdir -pfunction – 除非提供了mode ,并且现有目录与预期的目录具有不同的权限; 在这种情况下, OSError如前所述。

更新2

对于pathlib.Path.mkdir ,还有pathlib.Path.mkdir

 import pathlib pathlib.Path("/tmp/path/to/desired/directory").mkdir(parents=True, exist_ok=True) 

exist_ok参数是在Python 3.5中添加的。

在Python> = 3.2中,就是这样

 os.makedirs(path, exist_ok=True) 

在早期版本中,使用@ tzot的答案 。

这比捕获exception更容易:

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

免责声明此方法需要两个系统调用,在某些环境/条件下更容易受到竞争条件的影响。 如果你正在写一些比在一个受控环境下运行的简单的一次性脚本更复杂的东西,你最好只用一个系统调用来接受答案。

更新2012-07-27

我很想删除这个答案,但我认为在下面的评论线程中有价值。 就这样,我把它转换成维基。

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

 In [17]: from distutils.dir_util import mkpath In [18]: mkpath('./foo/bar') Out[18]: ['foo', 'foo/bar'] 

如果你的文件已经存在, mkdir -p会给你一个错误:

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

因此,如果os.path.isdir返回False (检查errno.EEXIST ),那么对以前的build议进行改进就是重新设置exception。

(更新)另见这个非常相似的问题 ; 我同意接受的答案(和警告),除了我会build议os.path.isdir而不是os.path.exists

(更新)根据评论中的build议,完整的function如下所示:

 import os def mkdirp(directory): if not os.path.isdir(directory): os.makedirs(directory) 

正如在其他解决scheme中提到的,我们希望能够在模仿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回答的评论所指出的那样,在实际创build目录之前,检查是否可以创build一个目录是有问题的:在此期间,不能确定是否有人更改了文件系统。 这也符合Python寻求宽恕的风格,而不是许可。

所以我们应该做的第一件事就是试着制作目录,如果出错了,找出原因。

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

mkdir -p

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

Python中类似的行为将引发exception。

所以我们必须弄清楚是不是这样。 不幸的是,我们不能。 我们从makedirs得到同样的错误信息,不pipe目录是否存在(好)或者是否存在阻止创build目录(坏)的文件。

解决所发生的事情的唯一方法是再次检查文件系统,看看是否有一个目录。 如果有,那么静静地回来,否则引发exception。

唯一的问题是现在的文件系统可能与makedirs被调用时处于不同的状态。 例如:一个文件存在导致makedirs失败,但现在一个目录是在它的位置。 这并不重要,因为只有在最后一次文件系统调用时,函数才会静默地退出而不会引发exception。

我认为Asa的答案基本上是正确的,但是您可以稍微扩展一下,使其更像mkdir -p

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

要么

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

这些都处理path已经默默存在,但让其他错误泡沫的情况。

从python3标准库的Pathlib :

 Path(mypath).mkdir(parents=True, exist_ok=True) 

如果父母是真实的,任何失踪的父母都是根据需要创build的。 它们是使用默认权限创build的,而不考虑模式(模仿POSIX mkdir -p命令)。 如果exist_ok为false(默认值),则如果目标目录已经存在,则会引发FileExistsError。

如果exist_ok为true,则FileExistsErrorexception将被忽略(与POSIX mkdir -p命令行为相同),但前提是最后一个path组件不是现有的非目录文件。

在版本3.5中进行了更改:添加了exist_ok参数。

函数声明;

 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 import tempfile path = tempfile.mktemp(dir=path) os.makedirs(path) os.rmdir(path) 

我已经成功地与以下个人,但我的function可能应该被称为像'确保这个目录存在':

 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 
 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的答案,但有一个错误修正了树的一部分已经存在