Как я могу безопасно создать вложенный каталог?


4253

Каков наиболее элегантный способ проверить, существует ли каталог, в который будет записан файл, и, если нет, создать каталог с помощью Python? Вот что я попробовал:

import os

file_path = "/my/directory/filename.txt"
directory = os.path.dirname(file_path)

try:
    os.stat(directory)
except:
    os.mkdir(directory)       

f = file(filename)

Как-то мне не хватало os.path.exists(спасибо Канджа, Блэр и Дуглас). Вот что у меня сейчас:

def ensure_dir(file_path):
    directory = os.path.dirname(file_path)
    if not os.path.exists(directory):
        os.makedirs(directory)

Есть ли флаг «открыть», который делает это автоматически?


27
В общем случае вам может потребоваться учитывать случай, когда в имени файла нет каталога. На моей машине dirname ('foo.txt') дает '', который не существует и приводит к сбою makedirs ().
Брайан Хокинс

11
В питоне 2.7 os.path.mkdirне существует. Это os.mkdir.
Древичко

6
если путь существует, нужно не только проверить, является ли он каталогом, а не обычным файлом или другим объектом (многие ответы проверяют это), также необходимо проверить, доступен ли он для записи (я не нашел ответа, который проверял это)
miracle173

9
Если вы пришли сюда для создания родительских каталогов строки пути к файлу p, вот мой фрагмент кода:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
Thamme Gowda

Ответы:


5197

На Python ≥ 3.5 используйте pathlib.Path.mkdir:

from pathlib import Path
Path("/my/directory").mkdir(parents=True, exist_ok=True)

Для более старых версий Python я вижу два ответа с хорошими качествами, каждый с небольшим недостатком, поэтому я сделаю это:

Попробуйте os.path.existsи рассмотрите os.makedirsдля создания.

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

Как отмечено в комментариях и в других местах, существует условие состязания - если каталог создается между вызовами os.path.existsи os.makedirsвызовами, os.makedirsпроизойдет сбой с помощью OSError. К сожалению, общий поиск OSErrorи продолжение не являются надежными, так как они будут игнорировать сбой при создании каталога из-за других факторов, таких как недостаточные разрешения, полный диск и т. Д.

Один из вариантов - перехватить OSErrorи изучить встроенный код ошибки (см. Существует ли кроссплатформенный способ получения информации из Python OSError ):

import os, errno

try:
    os.makedirs(directory)
except OSError as e:
    if e.errno != errno.EEXIST:
        raise

В качестве альтернативы может существовать второй os.path.exists, но предположим, что другой создал каталог после первой проверки, а затем удалил его до второй проверки - нас все еще можно обмануть.

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

Современные версии Python немного улучшают этот код, предоставляя FileExistsError(в версии 3.3+ ) ...

try:
    os.makedirs("path/to/directory")
except FileExistsError:
    # directory already exists
    pass

... и позволяя ключевому аргументу os.makedirsвызыватьсяexist_ok (в 3.2+).

os.makedirs("path/to/directory", exist_ok=True)  # succeeds even if directory exists.

5
Хорошим моментом является состояние гонки, но подход, описанный в stackoverflow.com/questions/273192/#273208 , замаскирует ошибку при создании каталога. Не расстраивайтесь из-за того, что проголосовали - вам не нравится ответ. Для этого и нужны голоса.
Блэр Конрад

27
Помните, что os.path.exists () не является бесплатным. Если нормальным случаем является то, что каталог будет там, то случай, когда он не будет, должен рассматриваться как исключение. Другими словами, попробуйте открыть и записать в свой файл, перехватить исключение OSError и, основываясь на errno, выполнить makedir () и повторить попытку или выполнить повторное повышение. Это создает дублирование кода, если вы не заключите запись в локальный метод.
Андрей

22
os.path.existsтакже возвращается Trueдля файла. Я отправил ответ на этот вопрос.
Acumenus

13
Как отмечалось здесь, в комментариях к другим ответам, exists_okпараметр to os.makedirs()может использоваться для описания того, как обрабатывается предшествующее существование пути, начиная с Python 3.2.
Боббл

6
os.mkdirs()может создавать непреднамеренные папки, если разделитель пути случайно пропущен, текущая папка не соответствует ожидаемой, элемент пути содержит разделитель пути. Если вы используете os.mkdir()эти ошибки, возникнет исключение, предупреждающее вас об их существовании.
Древичко

1242

Python 3.5+:

import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) 

pathlib.Path.mkdirкак используется выше, рекурсивно создает каталог и не вызывает исключение, если каталог уже существует. Если вам не нужно или вы хотите, чтобы родители были созданы, пропустите parentsаргумент.

Python 3.2+:

Использование pathlib:

Если можете, установите текущий pathlibбэкпорт с именем pathlib2. Не устанавливайте старый незарегистрированный бэкпорт с именем pathlib. Далее, обратитесь к разделу Python 3.5+ выше и используйте его так же.

При использовании Python 3.4, хотя он и поставляется pathlib, в нем отсутствует полезная exist_okопция. Бэкпорт предназначен для того, чтобы предложить более новую и превосходную реализацию, mkdirкоторая включает в себя этот отсутствующий параметр.

Использование os:

import os
os.makedirs(path, exist_ok=True)

os.makedirsкак используется выше, рекурсивно создает каталог и не вызывает исключение, если каталог уже существует. Он имеет необязательный exist_okаргумент, только если используется Python 3.2+ со значением по умолчанию False. Этот аргумент не существует в Python 2.x до 2.7. Таким образом, нет необходимости в ручной обработке исключений, как в Python 2.7.

Python 2.7+:

Использование pathlib:

Если можете, установите текущий pathlibбэкпорт с именем pathlib2. Не устанавливайте старый незарегистрированный бэкпорт с именем pathlib. Далее, обратитесь к разделу Python 3.5+ выше и используйте его так же.

Использование os:

import os
try: 
    os.makedirs(path)
except OSError:
    if not os.path.isdir(path):
        raise

В то время как наивное решение может сначала использовать, os.path.isdirа затем - os.makedirsприведенное выше решение меняет порядок этих двух операций. При этом он предотвращает общее состояние гонки, связанное с дублирующейся попыткой создания каталога, а также устраняет неоднозначность файлов из каталогов.

Обратите внимание, что захват исключения и его использование errnoимеют ограниченную полезность OSError: [Errno 17] File exists, т. Е. Возникает как errno.EEXISTдля файлов, так и для каталогов. Надежнее просто проверить, существует ли каталог.

Альтернатива:

mkpathсоздает вложенный каталог и ничего не делает, если каталог уже существует. Это работает как в Python 2, так и в 3.

import distutils.dir_util
distutils.dir_util.mkpath(path)

В соответствии с ошибкой 10948 , серьезным ограничением этой альтернативы является то, что она работает только один раз на процесс python для данного пути. Другими словами, если вы используете его для создания каталога, затем удаляете каталог изнутри или снаружи Python, а затем mkpathснова используете для воссоздания того же каталога, mkpathпросто молча будут использовать его неверную кэшированную информацию о том, что ранее создали каталог, и не будут на самом деле сделать каталог снова. Напротив, os.makedirsне полагается на любой такой кэш. Это ограничение может быть в порядке для некоторых приложений.


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


13
Насколько я могу судить, этот ответ охватывает практически все частные случаи. Я планирую обернуть это в «если не os.path.isdir ()», так как я ожидаю, что каталог будет существовать почти каждый раз, и таким образом я могу избежать исключения.
Чарльз Л.

5
@CharlesL. Исключение, вероятно, дешевле, чем дисковый ввод-вывод чека, если ваша причина в производительности.
jpmc26

1
@ jpmc26, но makedirs делает дополнительную статистику, umask, lstat, когда проверяет только бросок OSError.
kwarunek

4
Это неправильный ответ, так как он вводит потенциальное условие гонки ФС. Смотрите ответ от Аарона Холла.
сонный

4
как сказал @sleepycal, это страдает от того же состояния гонки, что и принятый ответ. Если между появлением ошибки и проверкой того, os.path.isdirкто-то еще удаляет папку, вы увидите ошибку, которая устарела и устарела, эта папка существует.
farmir

604

Использование try кроме и правильного кода ошибки из модуля errno избавляет от состояния гонки и является кроссплатформенным:

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise

Другими словами, мы пытаемся создать каталоги, но если они уже существуют, мы игнорируем ошибку. С другой стороны, сообщается о любой другой ошибке. Например, если вы заранее создадите dir 'a' и удалите из него все разрешения, вы получите OSErrorповышение с errno.EACCES(Отказано в доступе, ошибка 13).


24
Принятый ответ на самом деле опасен, потому что он имеет состояние гонки. Однако это проще, поэтому, если вы не знаете о состоянии гонки или думаете, что это не относится к вам, это будет вашим очевидным первым выбором.
Хейкки Тойвонен

15
Вызывает исключение только тогда, когда exception.errno != errno.EEXISTнепреднамеренно проигнорирует случай, когда путь существует, но это не-каталогный объект, такой как файл. В идеале, исключение следует вызывать, если путь не является каталогом.
Acumenus

178
Обратите внимание, что приведенный выше код эквивалентенos.makedirs(path,exist_ok=True)
Navin

58
@Navin exist_okПараметр был введен в Python 3.2. Его нет в Python 2.x. Я включу это в свой ответ.
Acumenus

26
@HeikkiToivonen С технической точки зрения, если другая программа изменяет каталоги и файлы в то же время, что и ваша программа, то вся ваша программа находится в одном гигантском состоянии гонки. Что может помешать другой программе просто удалить этот каталог после того, как код его создаст, и до того, как вы фактически поместите в него файлы?
jpmc26

102

Я бы лично рекомендовал вам использовать os.path.isdir()для тестирования вместо os.path.exists().

>>> os.path.exists('/tmp/dirname')
True
>>> os.path.exists('/tmp/dirname/filename.etc')
True
>>> os.path.isdir('/tmp/dirname/filename.etc')
False
>>> os.path.isdir('/tmp/fakedirname')
False

Если у тебя есть:

>>> dir = raw_input(":: ")

И глупый пользовательский ввод:

:: /tmp/dirname/filename.etc

... Вы filename.etcполучите каталог с именем, когда передадите этот аргумент, os.makedirs()если будете тестировать с os.path.exists().


8
Если вы используете только «isdir», не возникнет ли проблема при попытке создать каталог, и файл с таким именем уже существует?
MrWonderful

3
@MrWonderful Полученное исключение при создании каталога поверх существующего файла будет правильно отражать проблему обратно вызывающей стороне.
Дамиан Йеррик

79

Проверьте os.makedirs: (Он гарантирует, что полный путь существует.)
Чтобы обработать тот факт, что каталог может существовать, перехватите OSError. (Если exist_okесть False(по умолчанию), то OSErrorподнимается, если целевой каталог уже существует.)

import os
try:
    os.makedirs('./path/to/somewhere')
except OSError:
    pass

19
с помощью try / исключением вы будете маскировать ошибки при создании каталога, в случае, если каталог не существует, но по какой-то причине вы не можете его создать
Блэр Конрад,

3
OSErrorбудет поднят здесь, если путь является существующим файлом или каталогом. Я отправил ответ на этот вопрос.
Acumenus

4
Это на полпути там. Вам нужно проверить условие под-ошибки, OSErrorпрежде чем принимать решение игнорировать его. См. Stackoverflow.com/a/5032238/763269 .
Крис Джонсон

71

Начиная с Python 3.5, pathlib.Path.mkdirесть exist_okфлаг:

from pathlib import Path
path = Path('/my/directory/filename.txt')
path.parent.mkdir(parents=True, exist_ok=True) 
# path.parent ~ os.path.dirname(path)

Это рекурсивно создает каталог и не вызывает исключение, если каталог уже существует.

(так же, как os.makedirsполучил exist_okфлаг, начиная с Python 3.2, например os.makedirs(path, exist_ok=True))


46

Понимание специфики этой ситуации

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

filename = "/my/directory/filename.txt"
dir = os.path.dirname(filename)

Мы хотим избежать перезаписи встроенной функции dir. Кроме того, filepathили, возможно, fullfilepathэто, вероятно, лучшее семантическое имя, чем filenameэто было бы лучше написать:

import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)

Ваша конечная цель состоит в том, чтобы открыть этот файл, который вы изначально заявляете, для записи, но вы, по сути, приближаетесь к этой цели (основываясь на вашем коде) следующим образом, открывая файл для чтения :

if not os.path.exists(directory):
    os.makedirs(directory)
f = file(filename)

Предполагая открытие для чтения

Зачем вам делать каталог для файла, который вы ожидаете там и сможете прочитать?

Просто попробуйте открыть файл.

with open(filepath) as my_file:
    do_stuff(my_file)

Если каталог или файл отсутствуют, вы получите IOErrorсоответствующий номер ошибки: он errno.ENOENTбудет указывать на правильный номер ошибки независимо от вашей платформы. Вы можете поймать его, если хотите, например:

import errno
try:
    with open(filepath) as my_file:
        do_stuff(my_file)
except IOError as error:
    if error.errno == errno.ENOENT:
        print 'ignoring error because directory or file is not there'
    else:
        raise

Предполагая, что мы открыты для записи

Это наверное то, что вы хотите.

В этом случае мы, вероятно, не сталкиваемся ни с какими расами. Так что просто делайте, как вы, но учтите, что для записи вам нужно открыть с помощью wрежима (или aдобавить). На Python также рекомендуется использовать менеджер контекста для открытия файлов.

import os
if not os.path.exists(directory):
    os.makedirs(directory)
with open(filepath, 'w') as my_file:
    do_stuff(my_file)

Однако, скажем, у нас есть несколько процессов Python, которые пытаются поместить все свои данные в один и тот же каталог. Тогда мы можем иметь разногласия по поводу создания каталога. В этом случае лучше всего обернуть makedirsвызов в блок try-Кроме.

import os
import errno
if not os.path.exists(directory):
    try:
        os.makedirs(directory)
    except OSError as error:
        if error.errno != errno.EEXIST:
            raise
with open(filepath, 'w') as my_file:
    do_stuff(my_file)

34

Попробуйте os.path.existsфункцию

if not os.path.exists(dir):
    os.mkdir(dir)

3
Я собирался прокомментировать вопрос, но мы имеем в виду os.mkdir? Мой питон (2.5.2) не имеет os.path.mkdir ....
Блэр Конрад

1
Там нет os.path.mkdir()метода. Модуль os.path реализует некоторые полезные функции для путей .
Серж С.

31

Я изложил следующее. Это не совсем надежно, хотя.

import os

dirname = 'create/me'

try:
    os.makedirs(dirname)
except OSError:
    if os.path.exists(dirname):
        # We are nearly safe
        pass
    else:
        # There was an error on creation, so make sure we know about it
        raise

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



Две проблемы: (1) вам нужно проверить условие под-ошибки OSError, прежде чем принять решение о проверке os.path.exists- см. Stackoverflow.com/a/5032238/763269, и (2) успех os.path.existsне означает, что каталог существует, просто путь существует - это может быть файл, символическая ссылка или другой объект файловой системы.
Крис Джонсон

24

Проверить, существует ли каталог, и создать его при необходимости?

Прямой ответ на этот вопрос заключается в предположении простой ситуации, когда вы не ожидаете, что другие пользователи или процессы будут связываться с вашим каталогом:

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

или если создание каталога зависит от условий гонки (т. е. если после проверки пути существует, что-то еще, возможно, уже сделало это), сделайте это:

import errno
try:
    os.makedirs(d)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise

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

import tempfile

d = tempfile.mkdtemp()

Вот основные сведения из онлайн-документа:

mkdtemp(suffix='', prefix='tmp', dir=None)
    User-callable function to create and return a unique temporary
    directory.  The return value is the pathname of the directory.

    The directory is readable, writable, and searchable only by the
    creating user.

    Caller is responsible for deleting the directory when done with it.

Новое в Python 3.5: pathlib.Pathсexist_ok

Есть новый Pathобъект (начиная с 3.4) с множеством методов, которые можно использовать с путями - один из которых есть mkdir.

(Для контекста я отслеживаю своего еженедельного представителя с помощью скрипта. Вот соответствующие части кода из скрипта, которые позволяют мне избегать переполнения стека более одного раза в день для одних и тех же данных.)

Сначала соответствующий импорт:

from pathlib import Path
import tempfile

Нам не нужно иметь дело os.path.joinсейчас - просто соедините части пути с помощью /:

directory = Path(tempfile.gettempdir()) / 'sodata'

Затем я идемпотентно гарантирую, что каталог существует - exist_okаргумент обнаруживается в Python 3.5:

directory.mkdir(exist_ok=True)

Вот соответствующая часть документации :

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

Вот немного больше сценария - в моем случае я не подвержен условию гонки, у меня есть только один процесс, который ожидает, что каталог (или содержащиеся файлы) будет там, и у меня нет ничего, что пыталось бы удалить каталог.

todays_file = directory / str(datetime.datetime.utcnow().date())
if todays_file.exists():
    logger.info("todays_file exists: " + str(todays_file))
    df = pd.read_json(str(todays_file))

Pathобъекты должны быть приведены к тому, strчтобы другие API, ожидающие strпути, могли их использовать.

Возможно, Панды должны быть обновлены, чтобы принимать экземпляры абстрактного базового класса os.PathLike.


20

В Python 3.4 вы также можете использовать новый pathlibмодуль :

from pathlib import Path
path = Path("/my/directory/filename.txt")
try:
    if not path.parent.exists():
        path.parent.mkdir(parents=True)
except OSError:
    # handle error; you can also catch specific errors like
    # FileExistsError and so on.

@JanuszSkonieczny pypi.python.org/pypi/pathlib2 - это новый бэкпорт. Более старый не поддерживается.
Acumenus

Как это указано в первой строке readme; P. Но старый бэкпорт все еще действителен для ответа здесь. И нет именной головной боли. Не нужно объяснять, почему и когда использовать, pathlibи где pathlib2для новых пользователей, и я думаю, что профессионалы здесь определятся с устареванием;)
Janusz Skonieczny

13

В соответствующей документации по Python предлагается использовать стиль кодирования EAFP (проще просить прощения, чем разрешения) . Это означает, что код

try:
    os.makedirs(path)
except OSError as exception:
    if exception.errno != errno.EEXIST:
        raise
    else:
        print "\nBE CAREFUL! Directory %s already exists." % path

лучше альтернативы

if not os.path.exists(path):
    os.makedirs(path)
else:
    print "\nBE CAREFUL! Directory %s already exists." % path

Документация предполагает это именно из-за состояния гонки, обсуждаемого в этом вопросе. Кроме того, как другие упоминают здесь, есть преимущество в производительности при запросе один раз, а не дважды ОС. Наконец, аргумент, выдвигаемый, возможно, в пользу второго кода в некоторых случаях - когда разработчик знает среду, в которой выполняется приложение - может быть защищен только в том особом случае, когда программа создала частную среду для сам (и другие экземпляры той же программы).

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


12

В Python3 , os.makedirsустановка опор exist_ok. По умолчанию используется значение False, которое означает, что OSErrorбудет поднято, если целевой каталог уже существует. Установив exist_okв True, OSError(каталог существует) будет игнорироваться и каталог не будет создан.

os.makedirs(path,exist_ok=True)

В python2 , os.makedirsне поддерживает установку exist_ok. Вы можете использовать подход в ответе Хейкки-Тойвонена :

import os
import errno

def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise

11

Для однострочного решения вы можете использовать IPython.utils.path.ensure_dir_exists():

from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)

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


Новая документация IPython доступна здесь .
jkdev

3
IPythonМодуль абсолютно не гарантированно присутствовать. Он изначально присутствует на моем Mac, но не на любом из моих Linux-установок Python. По сути, это не один из модулей, перечисленных в указателе модулей Python .
Acumenus

1
Конечно. Для того чтобы установить пакет, просто запустить обычный pip install ipythonили включить зависимость в вашем requirements.txt или pom.xml . Документация: ipython.org/install.html
tashuhka

9

Ты можешь использовать mkpath

# Create a directory and any missing ancestor directories. 
# If the directory already exists, do nothing.

from distutils.dir_util import mkpath
mkpath("test")    

Обратите внимание, что он также создаст каталоги предков.

Это работает для Python 2 и 3.


2
distutils.dir_utilне является частью distutil public API и имеет проблемы в многопоточных средах: bugs.python.org/issue10948
Pod

1
Да. Как отмечалось в первом сообщении об ошибке, проблема в distutils.dir_util.mkpathтом, что если вы создаете каталог, затем удаляете его изнутри или снаружи Python, а затем mkpathснова используете , mkpathпросто воспользуетесь неверной кэшированной информацией о том, что ранее создал каталог, и на самом деле не сделать каталог снова. Напротив, os.makedirsне полагается на любой такой кэш.
Acumenus

8

Я использую os.path.exists(), вот сценарий Python 3, который можно использовать для проверки, существует ли каталог, создать его, если он не существует, и удалить его, если он существует (при желании).

Он предлагает пользователям ввести каталог и может быть легко изменен.


6

Вы можете использовать os.listdirдля этого:

import os
if 'dirName' in os.listdir('parentFolderPath')
    print('Directory Exists')

Это не отвечает на вопрос
Георгий

6

Я нашел это Q / A, и я был первоначально озадачен некоторыми сбоями и ошибками, которые я получал. Я работаю в Python 3 (v.3.5 в виртуальной среде Anaconda в системе Arch Linux x86_64).

Рассмотрим эту структуру каталогов:

└── output/         ## dir
   ├── corpus       ## file
   ├── corpus2/     ## dir
   └── subdir/      ## dir

Вот мои эксперименты / заметки, которые проясняют вещи:

# ----------------------------------------------------------------------------
# [1] /programming/273192/how-can-i-create-a-directory-if-it-does-not-exist

import pathlib

""" Notes:
        1.  Include a trailing slash at the end of the directory path
            ("Method 1," below).
        2.  If a subdirectory in your intended path matches an existing file
            with same name, you will get the following error:
            "NotADirectoryError: [Errno 20] Not a directory:" ...
"""
# Uncomment and try each of these "out_dir" paths, singly:

# ----------------------------------------------------------------------------
# METHOD 1:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## no error but no dir created (missing tailing /)
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but no file created (os.makedirs creates dir, not files!  ;-)
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# [2] https://docs.python.org/3/library/os.html#os.makedirs

# Uncomment these to run "Method 1":

#directory = os.path.dirname(out_dir)
#os.makedirs(directory, mode=0o777, exist_ok=True)

# ----------------------------------------------------------------------------
# METHOD 2:
# Re-running does not overwrite existing directories and files; no errors.

# out_dir = 'output/corpus3'                ## works
# out_dir = 'output/corpus3/'               ## works
# out_dir = 'output/corpus3/doc1'           ## works
# out_dir = 'output/corpus3/doc1/'          ## works
# out_dir = 'output/corpus3/doc1/doc.txt'   ## no error but creates a .../doc.txt./ dir
# out_dir = 'output/corpus2/tfidf/'         ## fails with "Errno 20" (existing file named "corpus2")
# out_dir = 'output/corpus3/tfidf/'         ## works
# out_dir = 'output/corpus3/a/b/c/d/'       ## works

# Uncomment these to run "Method 2":

#import os, errno
#try:
#       os.makedirs(out_dir)
#except OSError as e:
#       if e.errno != errno.EEXIST:
#               raise
# ----------------------------------------------------------------------------

Вывод: по моему мнению, «Метод 2» является более надежным.

[1] Как я могу создать каталог, если он не существует?

[2] https://docs.python.org/3/library/os.html#os.makedirs




5

Почему бы не использовать модуль подпроцесса, если он работает на компьютере, который поддерживает команду mkdirс -pпараметром? Работает на Python 2.7 и Python 3.6

from subprocess import call
call(['mkdir', '-p', 'path1/path2/path3'])

Должен сделать трюк на большинстве систем.

В ситуациях, когда переносимость не имеет значения (например, с помощью Docker), решение состоит из двух строк. Вам также не нужно добавлять логику, чтобы проверить, существуют ли каталоги или нет. Наконец, безопасно перезапускать без каких-либо побочных эффектов

Если вам нужна обработка ошибок:

from subprocess import check_call
try:
    check_call(['mkdir', '-p', 'path1/path2/path3'])
except:
    handle...

4

Если вы считаете следующее:

os.path.isdir('/tmp/dirname')

означает, что каталог (путь) существует И является каталогом. Так что для меня этот путь делает то, что мне нужно. Поэтому я могу убедиться, что это папка (а не файл) и существует.


Как это отвечает на вопрос о создании каталога?
Георгий

3

Вызовите функцию create_dir()в точке входа вашей программы / проекта.

import os

def create_dir(directory):
    if not os.path.exists(directory):
        print('Creating Directory '+directory)
        os.makedirs(directory)

create_dir('Project directory')

3

Вы должны установить полный путь перед созданием каталога:

import os,sys,inspect
import pathlib

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
your_folder = currentdir + "/" + "your_folder"

if not os.path.exists(your_folder):
   pathlib.Path(your_folder).mkdir(parents=True, exist_ok=True)

Это работает для меня и, надеюсь, это будет работать и для вас


1
import os
if os.path.isfile(filename):
    print "file exists"
else:
    "Your code here"

Где ваш код здесь, используйте команду (touch)

Это проверит, если файл там, если это не так, то он создаст его.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.