Mai mult
Cum pot crea condiții de siguranță o imbricate director?
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?
3872
25
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 considerareos.makedirs
pentru crearea.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 oOSError
. Din păcate, pătură-prindereaOSError
ș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):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+)......și permițând un cuvânt cheie argument pentru
os.makedirs "numit" exist_ok
(în 3.2+).Python 3.5+:
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.Python 3.2+:
Folosind
pathlib
:Dacă aveți posibilitatea, montați curent
pathlib
backport numepathlib2
. Nu instalați în vârstă neîntreținute backport numepathlib
. 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
:os.makedirs
cum este utilizat de mai sus recursiv creează directorul și nu ridică o excepție dacă directorul exista deja. Are opționalexist_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.Python 2.7+:
Folosind
pathlib
:Dacă aveți posibilitatea, montați curent
pathlib
backport numepathlib2
. Nu instalați în vârstă neîntreținute backport numepathlib
. Apoi, se referă la Piton de 3,5+ secțiunea de mai sus și să-l utilizați la fel.Folosind
os
:În timp ce o soluție naiv poate prima utilizare
os.calea.isdir
urmat deos.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 fi
este 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ă.Alternative:
mkpath
creează imbricate director, și nu face nimic dacă directorul exista deja. Acest lucru funcționează în ambele Python 2 și 3.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:
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 OSError
a 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 deos.calea.există()
.Dacă aveți:
Și o prostie de intrare de utilizator:
... 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.)Pornind de la Python 3.5,
pathlib.Calea.mkdir
a oexist_ok
flag: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)`)Perspective pe specificul de această situație
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:
Vrem pentru a evita suprascrierea funcție nativă,
dir
. De asemenea,filepath
sau poatefullfilepath
este, probabil, o mai bună semantic numele defilename
deci asta ar fi mai bine scris: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ă:
Presupunând deschiderea pentru citire
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.
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:Presupunând că ne-am're de deschidere pentru scriere
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.
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.Încerca
os.calea.există
funcțiaMi-am pus următoarele jos. L'nu e foarte simplu de lucrat, deși.
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ă.
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.:
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:
Dar, probabil, o mai bună abordare este de a se eschiva de resurse dispută problemă, prin utilizarea temporară directoare prin intermediul
tempfile
:Aici's esențialul din online doc:
# # # # Noi în Python 3.5:
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 estemkdir
.(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:
Am don't trebuie să se ocupe de
os.calea.alătură-te acum - doar alături de calea de piese cu un
/`:Apoi am idempotently asigura director există -
exist_ok
argument apare în Python 3.5:Aici's relevante, parte a documentatiei]2:
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.
"Cale" obiecte trebuie să fie constrâns să
str
înainte de alte Api-uri care așteptastr
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: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
este mai bine decât alternativa
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 setareaexist_ok
. Setarea implicită esteFalse
, care înseamnă oOSError` 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.În Python2,
os.makedirs
nu't suport setareaexist_ok
. Puteți utiliza abordarea din heikki-toivonen's a răspunde:Puteți utiliza
mkpath
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()
: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.
Puteți utiliza
os.listdir
pentru asta:Am văzut Heikki Toivonen și a-B-B's răspunsuri și a crezut că de această variație.
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:
Aici sunt experimentele mele/note, care clarifică lucrurile:
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
[2] https://docs.python.org/3/library/os.html#os.makedirs
Dacă se ia în considerare următoarele:
î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ă.