当前位置:  开发笔记 > 编程语言 > 正文

Python中的mkdir -p功能

如何解决《Python中的mkdir-p功能》经验,为你挑选了9个好方法。

有没有办法mkdir -p在Python中获得类似于shell的功能.我正在寻找除系统调用之外的解决方案.我确信代码少于20行,我想知道是否有人写过它?



1> tzot..:

mkdir -p 功能如下:

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

更新

对于Python≥3.2,os.makedirs有一个可选的第三个参数 exist_ok,当为true时,启用该mkdir -p功能 - 除非 mode提供,并且现有目录具有与预期目录不同的权限; 在这种情况下,OSError如前所述.

更新2

对于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习语,EAFP,或"要求宽恕而不是权限更容易".(参见http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Exceptions).其他不包含异常处理的实现具有潜在的竞争条件错误.
那么[distutils.dir_util.mkpath](http://docs.python.org/2/distutils/apiref.html#distutils.dir_util.mkpath)呢?这很简单,就像`mkpath('./ foo/bar')`
`除了OSError,exc:`for Python <2.5
@auraham,mkpath由于未记录的缓存而有一些意想不到的行为,如果你试图像mkdir -p那样使用它,可能会导致问题:http://bugs.python.org/issue10948.
@JohnnyLambada:对于Python≤2.5,你的意思是肯定的
@tzot:+1,但你真的不应该为了永远不会发生的情况而复杂的代码.
如果路径的最后一部分是文件,这似乎会失败,因为exc.errno等于errno.EEXIST,所以一切似乎都没问题,但实际上稍后使用该目录显然会失败.
优化异常处理?除了OSError为exc:如果是exc.errno!= errno.EEXIST或者不是os.path.isdir(path):raise
本着微观改进的精神,许多人会复制+粘贴:如何用`!=`替换`==`并删除`pass` /`else` :-)
谢谢!一位朋友指出,这种解决方案效率最高; 需要一次调用文件系统.在竞争文件系统上,这是要走的路.希望您的解决方案能获得更多的投票,并将其提升到第二位.
此版本还避免了竞争,因为文件系统可能在os.path.exist()和os.makedirs()之间发生变化

2> Fred Foo..:

在Python> = 3.2中,那就是

os.makedirs(path, exist_ok=True)

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


当脚本正在*(慢慢地)*迁移到Python3时,这应该是公认的答案.文档= http://docs.python.org/3.2/library/os#os.makedirs
@Jesse,`exist_ok`没有被删除,但是它不再检查现有目录的模式是否符合要求的模式

3> Joe Holloway..:

这比捕获异常更容易:

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

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

更新2012-07-27

我很想删除这个答案,但我认为下面的评论帖中有价值.因此,我将其转换为维基.


这样,在所有多任务操作系统中,使得makedirs失败的可能性降低,但并非不可能.这就像说"256个字符对于任何创建的路径都应该足够".
@TZ是的,我当然承认这一点.同样,如果没有原始海报的完整规范,我的假设是他/她想要一个可用于创建目录树的解决方案(如果尚未存在于简单脚本中),而不是具有SLA的HA企业生产解决方案.
@Asa那是什么例外,意外出错了.如果您没有权限,则异常会一直冒泡,您会注意到修复权限.应该如此.
@Asa当然.并且mkdir -p也会抱怨这一点.我错过了你的观点吗?
@ jholloway7:根据要求("mkdir -p"式功能)Asa的评论是不必要的.但是,我想知道您是否确实在调用.exists时可能不存在该目录,并且在调用.makedirs时存在该目录.
@setjmp我同意.您可能不希望在企业环境中使用此方法,但对于某些简单的脚本编写可以正常工作.我推断这就是你从你提出问题的方式中寻找的东西.

4> auraham..:

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

In [17]: from distutils.dir_util import mkpath

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


请注意,mkpath()会缓存目录,以便您不能使用不同的方法重新mkpath()一个已删除的目录:http://bugs.python.org/issue10948.
@romanows此外,该方法是私有的,以防其他人试图阅读错误报告,看看它是否已经"修复"(这不是一个错误).

5> Jacob Gabrie..:

mkdir -p 如果文件已存在,则会出错:

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

因此,对先前建议的改进将是返回(在检查时)raise异常.os.path.isdirFalseerrno.EEXIST

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

(更新)根据评论中的建议,完整功能如下所示:

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


如果它已作为A DIRECTORY存在,则mkdir -p不会出错.如果您要求它创建目录,并且已存在该名称的FILE,则会出错.

6> Ali SAID OMA..:

使用python3标准库中的Pathlib:

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

如果父母是真的,那么根据需要创建这条路径的任何失踪父母; 它们是使用默认权限创建的,不考虑模式(模仿POSIX mkdir -p命令).如果exist_ok为false(缺省值),则在目标目录已存在的情况下引发FileExistsError.

如果exist_ok为true,则将忽略FileExistsError异常(与POSIX mkdir -p命令相同),但前提是最后一个路径组件不是现有的非目录文件.

在版本3.5中更改:添加了exist_ok参数.


对于`python` <3.5,你可以使用`pathlib2`.`pip install pathlib2`; `from pathlib2 import Path`

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> davidavr..:

我认为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> Guray Celik..:

功能声明;

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))

推荐阅读
mobiledu2402851173
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有