Ceea ce este cel mai elegant mod de a verifica dacă directorul unui fișier este de gând să fie scrise pentru a exista, și dacă nu, creați directorul folosind Python? Aici este ceea ce am încercat:
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)
Cumva, am pierdut `os.calea.există (datorită kanja, Blair, și Douglas). Aceasta este ceea ce am acum:
def ensure_dir(file_path):
directory = os.path.dirname(file_path)
if not os.path.exists(directory):
os.makedirs(directory)
Este acolo un steag pentru "open", care face acest lucru în mod automat?
Eu văd două răspunsuri cu calități bune, fiecare cu un mic defect, așa că vor da mi iau pe asta:
Încerca os.calea.există
, și ia în considerare os.makedirs
pentru crearea.
import os
if not os.path.exists(directory):
os.makedirs(directory)
După cum sa menționat în comentarii și în altă parte, acolo's o condiție de rulare – dacă directorul este creat între os.calea.există " și " sistem de operare.makedirs
apeluri, os.makedirs
va eșua, cu o OSError
. Din păcate, pătură-prinderea OSError
și continuă nu este foarte simplu de manevrat, deoarece va ignora un eșec pentru a crea directorul din cauza altor factori, cum ar fi permisiuni insuficiente, plin de disc, etc.
O opțiune ar fi să prindă OSError
și de a examina încorporat cod de eroare (a se vedea Este un cross-platform mod de a obține informații de la Python OSError):
import os, errno
try:
os.makedirs(directory)
except OSError as e:
if e.errno != errno.EEXIST:
raise
Alternativ, ar putea fi un al doilea sistem de operare.calea.există, dar să presupunem că un alt creat directorul după prima verificare, apoi a scos-o înainte de cel de-al doilea – am putea fi păcălit.
În funcție de aplicație, pericolul de operațiuni simultane poate fi mai mult sau mai puțin decât pericolul reprezentat de alți factori, cum ar fi permisiunile de fișiere. Dezvoltatorul ar trebui să știu mai multe despre aplicație special dezvoltată și temperatura mediului înainte de a alege o implementare.
Versiunile moderne de Python îmbunătăți acest cod destul de un pic, atât prin expunerea FileExistsError
(în 3.3+)...
try:
os.makedirs("path/to/directory")
except FileExistsError:
# directory already exists
pass
...și permițând un cuvânt cheie argument pentru os.makedirs "numit" exist_ok
(în 3.2+).
os.makedirs("path/to/directory", exist_ok=True) # succeeds even if directory exists.
import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True)
pathlib.Calea.mkdir
cum este utilizat de mai sus recursiv creează directorul și nu ridică o excepție dacă directorul exista deja. Dacă tu nu't nevoie sau doresc părinții să fie creat, skip "părinții" argument.
Folosind pathlib
:
Dacă aveți posibilitatea, montați curent pathlib
backport nume pathlib2
. Nu instalați în vârstă neîntreținute backport nume pathlib
. Apoi, se referă la Piton de 3,5+ secțiunea de mai sus și să-l utilizați la fel.
Dacă folosind Python 3.4, chiar dacă acesta vine cu pathlib, este lipsă de util
exist_okopțiune. La backport este destinat să ofere o nouă și superioară punerea în aplicare a
mkdir` care include această opțiune de lipsă.
Folosind os
:
import os
os.makedirs(path, exist_ok=True)
os.makedirs
cum este utilizat de mai sus recursiv creează directorul și nu ridică o excepție dacă directorul exista deja. Are opțional exist_ok
argument numai dacă utilizarea Python 3.2+, cu o valoare implicită de "False". Acest argument nu există în Python 2.x până la 2.7. Ca atare, nu este nevoie de manual de manipulare excepție și cu Python 2.7.
Folosind pathlib
:
Dacă aveți posibilitatea, montați curent pathlib
backport nume pathlib2
. Nu instalați în vârstă neîntreținute backport nume pathlib
. Apoi, se referă la Piton de 3,5+ secțiunea de mai sus și să-l utilizați la fel.
Folosind os
:
import os
try:
os.makedirs(path)
except OSError:
if not os.path.isdir(path):
raise
În timp ce o soluție naiv poate prima utilizare os.calea.isdir
urmat de os.makedirs
, soluția de mai sus inversează ordinea celor două operațiuni. Procedând astfel, se previne o cursă comună condiția de a avea de-a face cu un duplicat tentativa de a crea directorul, și, de asemenea, separă fișiere din directoare.
Rețineți că capturarea excepție și folosirea errno va fieste de o utilitate limitată din cauza
OSError: [errno va fi 17] există Fișier, adică
errno va fi.EEXIST`, este crescut atât pentru fișiere și directoare. Este mult mai fiabile pur și simplu pentru a verifica dacă directorul nu există.
mkpath
creează imbricate director, și nu face nimic dacă directorul exista deja. Acest lucru funcționează în ambele Python 2 și 3.
import distutils.dir_util
distutils.dir_util.mkpath(path)
Pe Bug 10948, o limitare severă de această alternativă este că ea funcționează doar o dată pe python proces pentru o anumită cale. Cu alte cuvinte, dacă îl folosiți pentru a crea un director, apoi ștergeți directorul din interiorul sau din exteriorul Python, apoi utilizați mkpath din nou pentru a recrea același director,
mkpathva, pur și simplu, în tăcere, își folosească invalid info cache de a fi creat anterior director, și de fapt, nu vor face din nou directorul. În contrast,
os.makedirs` nu't să se bazeze pe orice astfel de cache. Această limitare poate fi bine pentru unele aplicații.
Cu privire la directorul's modul, vă rugăm să consultați documentația dacă îți pasă de ea.
Folosind încercați cu excepția și dreptul de codul de eroare de errno va fi modul scapa de starea de rasă și este cross-platform:
import os
import errno
def make_sure_path_exists(path):
try:
os.makedirs(path)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
Cu alte cuvinte, vom încerca pentru a crea directoare, dar dacă ele există deja am ignora eroare. Pe de altă parte, orice alte erori raportate. De exemplu, dacă veți crea dir 'un' în prealabil și elimina toate permisiunile de la ea, veți obține o OSErrora ridicat cu errno va fi.EACCES
(Permission denied, eroare 13).
Personal nu mi-ar recomandăm să utilizați os.calea.isdir()
pentru a testa în loc de os.calea.există()
.
>>> 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
Dacă aveți:
>>> dir = raw_input(":: ")
Și o prostie de intrare de utilizator:
:: /tmp/dirname/filename.etc
... Ai're de gând să se încheie cu un director cu numele filename.etc, atunci când trece ca argument pentru
os.makedirs()dacă testați cu
os.calea.există()`.
Verific os.makedirs
: (Se face sigur calea completă există.)
Să se ocupe de faptul directorul ar putea exista, prinde OSError. (Dacă
exist_okeste "Fals" (implicit), o
OSError` este crescut în cazul în directorul țintă există deja.)
import os
try:
os.makedirs('./path/to/somewhere')
except OSError:
pass
Pornind de la Python 3.5, pathlib.Calea.mkdir
a o exist_ok
flag:
from pathlib import Path
path = Path('/my/directory/filename.txt')
path.parent.mkdir(parents=True, exist_ok=True)
# path.parent ~ os.path.dirname(path)
Acest recursiv creează directorul și nu ridică o excepție dacă directorul exista deja.
(la fel ca os.makedirs
are o exist_okpavilion pornind de la python 3.2.e.g
os.makedirs(cale, exist_ok=True)`)
Vă dau un anumit fișier la o anumită cale și trage director din calea de fișier. Apoi, după asigurându-vă că aveți director, încercarea de a deschide un fișier pentru citire. Pentru a comenta pe acest cod:
filename = "/mea/director/fisier.txt" dir = os.calea.dirname(filename)
Vrem pentru a evita suprascrierea funcție nativă, dir
. De asemenea, filepath
sau poate fullfilepath
este, probabil, o mai bună semantic numele de filename
deci asta ar fi mai bine scris:
import os
filepath = '/my/directory/filename.txt'
directory = os.path.dirname(filepath)
Obiectivul dvs. final este de a deschide acest fișier, inițial stat, pentru scris, dar're în esență, să se apropie de acest obiectiv (bazat pe cod), cum ar fi acest lucru, care se deschide fișierul pentru lectură:
dacă nu sistemul de operare.calea.există(director): sistem de operare.makedirs(director) f = file(fisier)
De ce ai face un director pentru un fișier care te aștepți să fie acolo și să fie capabil să citească?
Doar încercarea de a deschide fișierul.
with open(filepath) as my_file:
do_stuff(my_file)
Dacă directorul sau fișierul este't acolo,'ll o IOError cu asociat un număr de eroare:
errno va fi.ENOENT` va indica corect numărul de eroare, indiferent de platforma. Puteți să-l prind, dacă doriți, de exemplu:
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
Acest lucru este probabil ceea ce're doresc.
În acest caz, noi, probabil, nu't cu care se confruntă orice condiții de rasă. Așa că fă cum ai fost tu, dar rețineți că pentru scris, aveți nevoie pentru a deschide cu " w "modul (sau" a " pentru a adăuga). L's, de asemenea, un Piton mai bună practică de a utiliza contextul manager pentru deschiderea fișierelor.
import os
if not os.path.exists(directory):
os.makedirs(directory)
with open(filepath, 'w') as my_file:
do_stuff(my_file)
Cu toate acestea, spune că avem mai multe Python procese care încearcă să pună toate datele lor în același director. Atunci am putea avea dispută asupra creației de director. În acest caz, se's cel mai bun pentru a încheia makedirs
apel la o probă, cu excepția bloc.
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)
Încerca os.calea.există
funcția
if not os.path.exists(dir):
os.mkdir(dir)
Mi-am pus următoarele jos. L'nu e foarte simplu de lucrat, deși.
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
Acum, cum am spus, acest lucru nu este chiar foarte simplu de manevrat, pentru că avem posibilitatea de a nu crea directorul, și un alt proces crearea în această perioadă.
Verificați dacă există un director și de a crea, dacă este necesar?
Răspunsul direct la acest lucru este, presupunând o situație simplă în cazul în care nu't aștepta alți utilizatori sau procese să fie încurcați cu directorul dvs.:
if not os.path.exists(d):
os.makedirs(d)
sau dacă face directorul este supusă unor condiții de rasă (de exemplu, dacă după verificarea există o cale, ceva poate au făcut-o deja) face acest lucru:
import errno
try:
os.makedirs(d)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
Dar, probabil, o mai bună abordare este de a se eschiva de resurse dispută problemă, prin utilizarea temporară directoare prin intermediul tempfile
:
import tempfile
d = tempfile.mkdtemp()
Aici's esențialul din online doc:
mkdtemp(sufix='', prefix='tmp', dir=None) Utilizator-nevărsat funcția de a crea și să se întoarcă un unic temporar director. Valoarea returnată este cale de director.
directorul este ușor de citit, scriere, și pot fi căutate doar de crearea de utilizator.
Apelantului este responsabil pentru ștergerea director atunci când ați terminat cu ea.
pathlib.Calea " cu " exist_ok
Nu's o nou Cale
obiect (ca de 3,4), cu o mulțime de metode ar trebui să fie utilizat cu căi - dintre care unul este mkdir
.
(Pentru context, am'm urmărire meu săptămânal rep cu un script. Aici's părțile relevante din codul de script-ul care permite-mi pentru a evita lovirea Stack Overflow mai mult de o dată pe zi pentru aceleași date.)
Prima importurilor relevante:
from pathlib import Path
import tempfile
Am don't trebuie să se ocupe de os.calea.alătură-te acum - doar alături de calea de piese cu un
/`:
directory = Path(tempfile.gettempdir()) / 'sodata'
Apoi am idempotently asigura director există - exist_ok
argument apare în Python 3.5:
directory.mkdir(exist_ok=True)
Aici's relevante, parte a documentatiei]2:
Dacă
exist_ok este adevărat,
FileExistsErrorexcepții vor fi ignorate (același comportament ca
POSIX mkdir -p` comanda), dar numai dacă ultima componentă cale nu este existent non-director de fișiere.
Aici's un pic mai mult de script - în cazul meu, am'm nu face obiectul unei stări, am doar un proces care se așteaptă ca director (sau fișierele conținute) pentru a fi acolo, și eu nu't au nimic de încercarea de a elimina director.
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))
"Cale" obiecte trebuie să fie constrâns să str
înainte de alte Api-uri care aștepta str
căi le pot folosi.
Poate că Panda ar trebui să fie actualizat pentru a accepta cazuri de clasă abstractă de bază, os.PathLike
.
În Python 3.4 puteți utiliza, de asemenea, de brand nou pathlib
module:
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.
De relevante Python documentația sugerează utilizarea EAFP stil de codificare (mai Ușor pentru a Cere Iertarea decât Permisiunea). Acest lucru înseamnă că codul
try:
os.makedirs(path)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
else:
print "\nBE CAREFUL! Directory %s already exists." % path
este mai bine decât alternativa
if not os.path.exists(path):
os.makedirs(path)
else:
print "\nBE CAREFUL! Directory %s already exists." % path
Documentația sugerează asta exact din cauza stări de discutat în această întrebare. În plus, ca și alții menționează aici, există un avantaj de performanță în interogarea odată, în loc de două ori sistemul de OPERARE. În cele din urmă, argumentul plasate înainte, potențial, în favoarea celui de-al doilea cod în unele cazuri-atunci când dezvoltatorul știe mediului aplicația se execută-poate fi invocată în cazul special în care programul a înființat un mediu privat pentru sine (și alte instanțe ale aceluiași program).
Chiar și în acest caz, aceasta este o practică proastă și poate duce la mult timp inutil de depanare. De exemplu, faptul că ne-am setat permisiunile pentru un director nu ar trebui să ne lase cu impresia permisiunile sunt setate corespunzător pentru scopurile noastre. Un director de mamă ar putea fi montat cu alte permisiuni. În general, un program ar trebui să lucreze întotdeauna în mod corect și programatorul nu trebuie să se aștepte un mediu specific.
În Python3, os.makedirs
suporta setarea exist_ok
. Setarea implicită este False
, care înseamnă o OSError` va fi ridicat în cazul în directorul țintă există deja. Prin setarea
exist_oka
Adevărat,
OSError`` (director există) vor fi ignorate și directorul nu va fi creat.
os.makedirs(path,exist_ok=True)
În Python2, os.makedirs
nu't suport setarea exist_ok
. Puteți utiliza abordarea din heikki-toivonen's a răspunde:
import os
import errno
def make_sure_path_exists(path):
try:
os.makedirs(path)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
Puteți utiliza mkpath
# Create a directory and any missing ancestor directories.
# If the directory already exists, do nothing.
from distutils.dir_util import mkpath
mkpath("test")
Rețineți că se va crea strămoșul directoare.
Acesta funcționează pentru Python 2 și 3.
Pentru un one-liner soluție, puteți utiliza IPython.utils.path.ensure_dir_exists()
:
from IPython.utils.path import ensure_dir_exists
ensure_dir_exists(dir)
De documentația: Ensure că un director există. Dacă nu există, încercați să-l creeze și să protejeze împotriva unei stări dacă un alt proces este de a face același lucru.
Eu folosesc sistem de operare.calea.există()`, aici este un script Python 3, care poate fi folosit pentru a verifica dacă un director există, creați unul dacă nu există, și ștergeți-l dacă există (dacă se dorește).
Se solicită utilizatorilor pentru intrare de director și pot fi ușor modificate.
Am văzut Heikki Toivonen și a-B-B's răspunsuri și a crezut că de această variație.
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
Am găsit asta Q/O și inițial am fost mirat de unele eșecuri și erori am fost obtinerea. Am de lucru în Python 3 (v. 3.5 într-un Anaconda mediu virtual pe un Arch Linux x86_64 sistem).
Ia în considerare această structură de directoare:
└── output/ ## dir
├── corpus ## file
├── corpus2/ ## dir
└── subdir/ ## dir
Aici sunt experimentele mele/note, care clarifică lucrurile:
# ----------------------------------------------------------------------------
# [1] https://stackoverflow.com/questions/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
# ----------------------------------------------------------------------------
Concluzie: în opinia mea, "Metoda 2" este mai robust.
[1] https://stackoverflow.com/questions/273192/how-can-i-create-a-directory-if-it-does-not-exist
Dacă se ia în considerare următoarele:
os.path.isdir('/tmp/dirname')
înseamnă un director (path) există ȘI este un director. Deci, pentru mine acest drum face ceea ce am nevoie. Deci, eu pot asigurați-vă că acesta este folderul (nu un fișier) și există.