функциональность mkdir-p в Python [дубликат]



этот вопрос уже есть ответ здесь:



есть ли способ получить функциональность, аналогичную mkdir -p на оболочке изнутри Python. Я ищу решение, отличное от системного вызова. Я уверен, что код составляет менее 20 строк, и я интересно, если кто-то уже написал его?

603   12  

12 ответов:

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)

The

в Python >=3.2, это

os.makedirs(path, exist_ok=True)

в более ранних версиях, используйте @tzot это!--5-->.

Это проще, чем поймать исключение:

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

таким образом, уточнение к предыдущим предложениям было бы повторно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) 

как уже упоминалось в других решениях, мы хотим иметь возможность попасть в файловую систему один раз, имитируя поведение 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 просить прощения, а не разрешения.

Итак, первое, что мы должны сделать, это попытаться сделать каталог, а затем, если все пойдет не так, выяснить, почему.

С mkdir -p:

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

аналогичное поведение в Python будет заключаться в том, чтобы поднять исключение.

так что мы должны решить, если это было так. К сожалению, мы не можем. Мы получаем то же сообщение об ошибке от makedirs, существует ли каталог (хорошие) или файл существует, препятствующих созданию каталога (БАД).

единственный способ выяснить, что произошло, это снова проверить файловую систему, чтобы увидеть, есть ли там каталог. Если есть, то вернитесь молча, иначе вызовите исключение.

единственная проблема заключается в том, что файл система может быть в другом состоянии, чем сейчас, когда makedirs называлась. например: файл существовал, вызывая сбой makedirs, но теперь каталог находится на своем месте. Это на самом деле не имеет большого значения, потому что функция будет выходить только молча, не вызывая исключения, когда во время последнего вызова файловой системы каталог существовал.

Я думаю, что ответ 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

Они оба обрабатывают случай, когда путь уже существует молча, но пусть другие ошибки всплывают.

С Pathlib из стандартной библиотеки python3:

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

если parents имеет значение true, все отсутствующие родители этого пути создаются как необходимо; они создаются с разрешениями по умолчанию без принятия учитывается режим (имитация команды POSIX mkdir-p). Если exist_ok имеет значение false (по умолчанию), то вызывается FileExistsError, если целевой каталог уже существует.

если exist_ok имеет значение true, fileexistserror исключения будут игнорируется (то же самое поведение как команда POSIX mkdir-p), но только если последний путь компонент не является существующим файлом без каталога.

изменено в версии 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)

У меня был успех со следующим лично, но моя функция, вероятно, должна называться что-то вроде "убедитесь, что этот каталог существует":

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, но с исправленной ошибкой, где часть дерева уже существует

Comments

    Ничего не найдено.