Python 中的 mkdir -p 功能[重复]
- 2025-01-13 08:52:00
- admin 原创
- 128
问题描述:
有没有办法mkdir -p
在 Python 内部获得类似于 shell 的功能?我正在寻找系统调用以外的解决方案。我确定代码少于 20 行,我想知道是否有人已经编写了它?
解决方案 1:
对于 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
解决方案 2:
在 Python >=3.2 中,这是
os.makedirs(path, exist_ok=True)
在早期版本中,使用@tzot 的答案。
解决方案 3:
这比捕获异常更容易:
import os
if not os.path.exists(...):
os.makedirs(...)
免责声明这种方法需要两个系统调用,在某些环境/条件下更容易受到竞争条件的影响。如果您要编写比在受控环境中运行的简单一次性脚本更复杂的东西,最好采用只需要一个系统调用的可接受答案。
更新日期 2012-07-27
我很想删除这个答案,但我认为下面的评论很有价值。因此,我将其转换为 wiki。
解决方案 4:
最近,我发现了这个distutils.dir_util.mkpath:
In [17]: from distutils.dir_util import mkpath
In [18]: mkpath('./foo/bar')
Out[18]: ['foo', 'foo/bar']
解决方案 5:
使用python3标准库中的Pathlib:
Path(mypath).mkdir(parents=True, exist_ok=True)
如果 parents 为真,则根据需要创建此路径的任何缺失父级;它们使用默认权限创建,而不考虑模式(模仿 POSIX mkdir -p 命令)。如果 exist_ok 为假(默认),则如果目标目录已存在,则会引发 FileExistsError。
如果 exist_ok 为真,则 FileExistsError 异常将被忽略(行为与 POSIX mkdir -p 命令相同),但前提是最后一个路径组件不是现有的非目录文件。
在 3.5 版更改:添加了 exist_ok 参数。
解决方案 6:
mkdir -p
如果文件已经存在,则会给出错误:
$ touch /tmp/foo
$ mkdir -p /tmp/foo
mkdir: cannot create directory `/tmp/foo': File exists
因此,对之前建议的改进是重新处理raise
异常(如果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)
解决方案 7:
正如在其他解决方案中提到的,我们希望能够在模仿的行为的同时访问文件系统一次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 失败,但现在目录已取代该文件。这其实并不重要,因为只有在最后一次文件系统调用时目录存在时,该函数才会默默退出而不引发异常。
解决方案 8:
我认为 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
这两种方法都可以处理路径已经存在但其他错误冒出来的情况。
解决方案 9:
函数声明;
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))
解决方案 10:
import os
import tempfile
path = tempfile.mktemp(dir=path)
os.makedirs(path)
os.rmdir(path)
解决方案 11:
我个人已经成功完成了以下操作,但我的功能可能应该被称为“确保该目录存在”:
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
解决方案 12:
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 的答案,但修复了树的一部分已经存在的错误
扫码咨询,免费领取项目管理大礼包!