有没有一种方法可以在Python中获得类似于shell中mkdir -p
的功能?我想要的是除系统调用之外的解决方案。我相信代码不到20行,想知道是否有人已经写过这个功能?
有没有一种方法可以在Python中获得类似于shell中mkdir -p
的功能?我想要的是除系统调用之外的解决方案。我相信代码不到20行,想知道是否有人已经写过这个功能?
对于Python ≥ 3.5版本,请使用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
函数有一个可选的第三个参数 exist_ok
。当该参数为 True
时,启用了 mkdir -p
的功能,除非提供了 mode
并且现有目录的权限与预期权限不同;在这种情况下,仍然会像以前一样引发 OSError
异常:
import os
os.makedirs("/tmp/path/to/desired/directory", exist_ok=True)
对于更早版本的Python,您可以使用 os.makedirs
并忽略错误:
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
# possibly handle other errno cases here, otherwise finally:
else:
raise
!=
代替==
并删除pass
/else
:-) - Will Hardy这比捕获异常更容易:
import os
if not os.path.exists(...):
os.makedirs(...)
免责声明:这种方法需要两个系统调用,更容易在某些环境/条件下出现竞争条件。如果你要编写的程序比在受控环境中运行的简单临时脚本更为复杂,那么最好采用只需要一个系统调用的被接受答案。
更新于2012-07-27
我想删除这个答案,但我认为下面的评论线程有价值。因此,我将其转换为Wiki。
最近,我发现了这个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
时),则重新引发异常。
(更新)还可以参见这个非常相似的问题;我赞同被接受的答案(以及注意事项),不过我推荐使用os.path.isdir
而不是os.path.exists
。
(更新)根据评论中的建议,完整的函数应该如下所示:
import os
def mkdirp(directory):
if not os.path.isdir(directory):
os.makedirs(directory)
pathlib
,那么Path("/tmp/my/file").mkdir(parents=True, exist_ok=True)
也会表现出相同的行为。它将引发一个FileExistsError
异常。 - user3064538使用Python3标准库中的Pathlib:
Path(mypath).mkdir(parents=True, exist_ok=True)
如果 parents 为 True,该路径中缺失的任何父级目录都将根据需要创建;它们将使用默认权限创建,而不考虑模式(效仿 POSIX 的 mkdir -p 命令)。如果 exist_ok 为 False(默认值),则如果目标目录已存在,则会引发 FileExistsError 异常。pip install pathlib2
,然后在代码中添加导入语句:from pathlib2 import Path
。 - Eyal Levin正如其他解决方案中提到的那样,我们希望在模拟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失败时已存在文件,但现在替换为一个目录。这并不重要,因为在最后一次文件系统调用时,函数仅在目录存在时静默退出而不引发异常。
os.makedirs(path, exist_ok=True)
: - Erik Aronesty我认为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
这两种方式都可以在路径已经存在的情况下默默地处理,但会让其他错误冒出来。
Python 2.7.6 ... [GCC 4.8.2] on linux2
上,至少看起来应该是os.mkdir
而不是os.mkdirs
。 - tsbertalan函数声明;
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)
mkdir -p
。例如,echo prefix-{Subfolder1,Subfolder2}
将显示 "prefix-Subfolder1 prefix-Subfolder2"。 - jejese