Як я можу безпечно створити вкладений каталог?


4243

Який найелегантніший спосіб перевірити, чи існує файл файлу в каталог, а якщо ні, створити каталог за допомогою 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
У python 2.7 os.path.mkdirне існує. Це os.mkdir.
drevicko

6
якщо шлях існує, потрібно не тільки перевірити, чи це каталог, а не звичайний файл чи інший об'єкт (багато відповідей це перевіряє), також потрібно перевірити, чи він написаний (я не знайшов відповіді, що це перевірило)
чудо173

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

Відповіді:


5184

На 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і вивчити вбудований код помилки (див. Чи існує міжплатформенний спосіб отримання інформації з OSError Python ):

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.makedirsexist_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параметр, який os.makedirs()можна використовувати для покриття способу обробки попереднього існування шляху, починаючи з Python 3.2.
Боббл

6
os.mkdirs()може створити ненавмисні папки, якщо випадково залишився роздільник шляху, поточна папка не є такою, як очікувалося, елемент шляху містить роздільник шляху. Якщо ви використовуєте os.mkdir()ці помилки, ви отримаєте виняток, попереджаючи про їх існування.
drevicko

1241

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, а потім mkpathзнову використовуйте для відтворення того ж каталогу, mkpathпросто мовчки використовуватиме свою недійсну інформацію про кешування попередньо створеного каталогу, і не буде фактично зробити каталог знову. На відміну від цього, os.makedirsне покладається на жоден такий кеш. Для деяких програм це обмеження може бути нормальним.


Що стосується самого каталогу режиму , будь ласка , зверніться до документації , якщо ви дбаєте про нього.


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

5
@CharlesL. Виняток, ймовірно, дешевше, ніж дисковий ввід чека, якщо ваша причина - продуктивність.
jpmc26

1
@ jpmc26, але makedirs робить додаткові stat, umask, lstat лише під час перевірки, щоб кинути OSError.
kwarunek

4
Це неправильна відповідь, оскільки він представляє потенційного кондиціонера FS. Дивіться відповідь від Аарона Холла.
сонливий

4
як сказав @sleepycal, це страждає від подібних умов перегонів, як прийнята відповідь. Якщо між підняттям помилки та перевіркою того, що os.path.isdirхтось інший видаляє папку, ви підберете неправильну, застарілу та заплутану помилку, що існує в папці.
фермер

604

Використовуючи спробу за винятком і правильний код помилки з модуля 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(Permissions відмовлено, помилка 13).


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

15
Підвищення винятку лише тоді, коли exception.errno != errno.EEXISTненавмисно ігнорує випадок, коли шлях існує, але є об'єктом, який не є каталогом, таким як файл. Виняток слід в ідеалі збільшувати, якщо шлях є об'єктом, який не є каталогом.
Акумен

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 Отриманий виняток при створенні каталогу над існуючим файлом правильно відображатиме проблему, що повертається до абонента.
Damian Yerrick

79

Перевірте os.makedirs: (Це гарантує, що існує повний шлях.)
Щоб обробити той факт, що каталог може існувати, знайдіть OSError. (Якщо exist_okє False(за замовчуванням), OSErrorпіднімається, якщо цільовий каталог вже існує.)

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

19
за допомогою спроби / за винятком, ви замаскуєте помилки у створенні каталогу, у тому випадку, коли каталог не існував, але чомусь ви не можете його зробити
Блер Конрад

3
OSErrorтут буде піднято, якщо шлях - це вже існуючий файл або каталог. Я опублікував відповідь, щоб вирішити це.
Акумен

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виклик у випробувальний блок.

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 - це новіший заплід . Старший - непорушений.
Акумен

Як зазначено в першому рядку readme; P. Але старий бекпорт все ще діє для відповіді тут. І головного болю не називають. Не потрібно пояснювати, чому і коли користуватися pathlibі де pathlib2для нових користувачів, і я думаю, що профі тут розберуть застаріння;)
Janusz Skonieczny

13

Відповідна документація Python передбачає використання ЕСПЦ кодування стиль (Легше попросити вибачення , ніж дозволу) . Це означає, що код

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

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

Навіть у цьому випадку це погана практика і може призвести до тривалої марної налагодження. Наприклад, те, що ми встановлюємо дозволи для каталогу, не повинно залишати нас, якщо дозволи на покази встановлені належним чином для наших цілей. Батьківський каталог може бути змонтований з іншими дозволами. Загалом, програма завжди повинна працювати правильно, і програміст не повинен очікувати одного конкретного середовища.


11

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

os.makedirs(path,exist_ok=True)

У python2 , os.makedirsне підтримує установку exist_ok. Ви можете використовувати підхід у відповіді heikki-toivonen :

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 громадського API і мають проблеми в багатопоточних середовищах: bugs.python.org/issue10948
Pod

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

8

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

Це спонукає користувачів до введення каталогу і його можна легко змінити.


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


6

Я побачив відповіді Хейкі Тойвонен та ABB і подумав про цю варіацію.

import os
import errno

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


5

Чому б не використовувати підпроцесорний модуль, якщо він працює на машині, що підтримує команду mkdirз -pопцією? Працює на python 2.7 та python 3.6

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

Слід зробити фокус у більшості систем.

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

Якщо вам потрібна робота з помилками:

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.