Jak mogę bezpiecznie utworzyć katalog zagnieżdżony?


4241

Jaki jest najbardziej elegancki sposób sprawdzenia, czy istnieje katalog, w którym ma zostać zapisany plik, a jeśli nie, utwórz katalog za pomocą Pythona? Oto, co próbowałem:

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)

Jakoś tęskniłem os.path.exists(dzięki kanja, Blair i Douglas). Oto co mam teraz:

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

Czy istnieje flaga „otwarta”, która sprawia, że ​​dzieje się to automatycznie?


27
Zasadniczo może być konieczne uwzględnienie przypadku, w którym nie ma katalogu w nazwie pliku. Na moim komputerze dirname („foo.txt”) daje „”, który nie istnieje i powoduje niepowodzenie makedirs ().
Brian Hawkins

11
W Pythonie 2.7 os.path.mkdirnie istnieje. Jest os.mkdir.
drevicko,

6
jeśli ścieżka istnieje, należy nie tylko sprawdzić, czy jest to katalog, a nie zwykły plik lub inny obiekt (wiele odpowiedzi to sprawdza), należy również sprawdzić, czy jest zapisywalny (nie znalazłem odpowiedzi, która to sprawdzała)
miracle173

9
Jeśli przyszedłeś tutaj, aby utworzyć nadrzędne katalogi ciągu ścieżki do pliku p, oto mój fragment kodu:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
Thamme Gowda,

Odpowiedzi:


5183

W Pythonie ≥ 3.5 użyj pathlib.Path.mkdir:

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

W przypadku starszych wersji Pythona widzę dwie odpowiedzi o dobrych cechach, każda z małą wadą, więc przyjmuję to:

Spróbuj os.path.existsi zastanów się os.makedirsnad stworzeniem.

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

Jak zauważono w komentarzach i gdzie indziej, istnieje warunek wyścigu - jeśli katalog zostanie utworzony między połączeniami os.path.existsi, os.makedirspołączenie os.makedirszakończy się niepowodzeniem OSError. Niestety łapanie OSErrori kontynuowanie koców nie jest niezawodne, ponieważ zignoruje niepowodzenie tworzenia katalogu z powodu innych czynników, takich jak niewystarczające uprawnienia, pełny dysk itp.

Jedną z opcji byłoby przechwycenie OSErrori sprawdzenie osadzonego kodu błędu (zobacz Czy istnieje wieloplatformowy sposób uzyskiwania informacji z OSError Pythona ):

import os, errno

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

Alternatywnie może istnieć sekunda os.path.exists, ale załóżmy, że inny utworzył katalog po pierwszym sprawdzeniu, a następnie usunął go przed drugim - nadal możemy się oszukać.

W zależności od aplikacji niebezpieczeństwo równoczesnych operacji może być większe lub mniejsze niż niebezpieczeństwo stwarzane przez inne czynniki, takie jak uprawnienia do plików. Deweloper musiałby dowiedzieć się więcej o konkretnej aplikacji i jej oczekiwanym środowisku przed wybraniem implementacji.

Nowoczesne wersje Pythona znacznie poprawiają ten kod, zarówno poprzez ujawnienie FileExistsError(w wersji 3.3 +) ...

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

... i pozwalając argument słowa kluczowego dla os.makedirsnazywanyexist_ok (w 3.2 lub nowszym).

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

5
Warunkiem wyścigu jest dobra uwaga, ale podejście z stackoverflow.com/questions/273192/#273208 ukryje błąd podczas tworzenia katalogu. Nie przejmuj się głosowaniem - nie podoba ci się odpowiedź. Po to są głosy.
Blair Conrad,

27
Pamiętaj, że os.path.exists () nie jest darmowy. Jeśli normalnym przypadkiem jest to, że katalog będzie tam, to przypadek, w którym go nie ma, powinien być traktowany jako wyjątek. Innymi słowy, spróbuj otworzyć i zapisać do pliku, złap wyjątek OSError i, na podstawie errno, wykonaj makedir () i spróbuj ponownie lub ponownie przebij. Powoduje to powielanie kodu, chyba że zapiszesz zapis w lokalnej metodzie.
Andrew

22
os.path.existszwraca również Trueplik. Wysłałem odpowiedź, aby rozwiązać ten problem.
Acumenus

13
Jak zauważyli komentatorzy innych odpowiedzi tutaj, exists_okparametr, os.makedirs()którego można użyć, aby opisać, jak obsługiwane jest wcześniejsze istnienie ścieżki, od Python 3.2.
Bobble

6
os.mkdirs()może tworzyć niezamierzone foldery, jeśli przypadkowo pominięto separator ścieżki, bieżący folder nie jest zgodny z oczekiwaniami, element ścieżki zawiera separator ścieżki. Jeśli użyjesz os.mkdir()tych błędów, pojawi się wyjątek, ostrzegający o ich istnieniu.
drevicko,

1240

Python 3.5+:

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

pathlib.Path.mkdirzgodnie z powyższym rekurencyjnie tworzy katalog i nie zgłasza wyjątku, jeśli katalog już istnieje. Jeśli nie potrzebujesz lub nie chcesz, aby rodzice zostali utworzeni, pomiń parentsargument.

Python 3.2+:

Używanie pathlib:

Jeśli możesz, zainstaluj bieżący pathlibbackport o nazwie pathlib2. Nie instaluj starszego nieobsługiwanego backportu o nazwie pathlib. Następnie zapoznaj się z sekcją Python 3.5+ powyżej i użyj jej w ten sam sposób.

Jeśli używasz Pythona 3.4, mimo że pathlibjest w zestawie, brakuje użytecznej exist_okopcji. Backport ma na celu zaoferowanie nowszej i lepszej implementacji, mkdirktóra zawiera tę brakującą opcję.

Używanie os:

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

os.makedirszgodnie z powyższym rekurencyjnie tworzy katalog i nie zgłasza wyjątku, jeśli katalog już istnieje. Ma opcjonalny exist_okargument tylko w przypadku używania języka Python 3.2+ z wartością domyślną False. Ten argument nie istnieje w Pythonie 2.x do wersji 2.7. W związku z tym nie ma potrzeby ręcznego obsługiwania wyjątków, jak w Pythonie 2.7.

Python 2.7+:

Używanie pathlib:

Jeśli możesz, zainstaluj bieżący pathlibbackport o nazwie pathlib2. Nie instaluj starszego nieobsługiwanego backportu o nazwie pathlib. Następnie zapoznaj się z sekcją Python 3.5+ powyżej i użyj jej w ten sam sposób.

Używanie os:

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

Podczas gdy najpierw można zastosować naiwne rozwiązanie, os.path.isdira następnie os.makedirspowyższe rozwiązanie odwraca kolejność dwóch operacji. W ten sposób zapobiega powszechnemu wyścigowi związanemu ze zduplikowaną próbą utworzenia katalogu, a także ujednoznacznia pliki z katalogów.

Zauważ, że przechwycenie wyjątku i użycie errnoma ograniczoną użyteczność, ponieważ OSError: [Errno 17] File exists, tj. errno.EEXISTJest podniesiony zarówno dla plików, jak i katalogów. Bardziej niezawodne jest po prostu sprawdzenie, czy katalog istnieje.

Alternatywny:

mkpathtworzy zagnieżdżony katalog i nic nie robi, jeśli katalog już istnieje. Działa to zarówno w Pythonie 2, jak i 3.

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

W przypadku błędu 10948 poważnym ograniczeniem tej alternatywy jest to, że działa ona tylko raz na proces Pythona dla danej ścieżki. Innymi słowy, jeśli użyjesz go do utworzenia katalogu, usuń go z wewnątrz lub z zewnątrz Pythona, a następnie użyj mkpathponownie, aby odtworzyć ten sam katalog, mkpathpo prostu po cichu użyje swoich niepoprawnych informacji buforowanych o wcześniejszym utworzeniu katalogu i nie będzie faktycznie ponownie utwórz katalog. W przeciwieństwie do tego, os.makedirsnie polega na takiej pamięci podręcznej. To ograniczenie może być odpowiednie w przypadku niektórych aplikacji.


Jeśli chodzi o tryb katalogu , zapoznaj się z dokumentacją, jeśli cię to obchodzi.


13
Ta odpowiedź obejmuje prawie każdy szczególny przypadek, o ile wiem. Planuję zawinąć to w „if not os.path.isdir ()”, ponieważ spodziewam się, że katalog istnieje prawie za każdym razem i mogę w ten sposób uniknąć wyjątku.
Charles L.

5
@CharlesL. Wyjątkiem jest prawdopodobnie tańszy niż IO dysku czeku, jeśli powodem jest wydajność.
jpmc26

1
@ jpmc26, ale makedirs robi dodatkowe statystyki, umask, lstat, gdy sprawdza tylko, czy wyrzucić OSError.
kwarunek

4
To zła odpowiedź, ponieważ wprowadza potencjalne warunki wyścigu FS. Zobacz odpowiedź Aarona Hall.
sleepycal

4
jak powiedział @sleepycal, cierpi to na podobny warunek rasowy, co przyjęta odpowiedź. Jeśli między podniesieniem błędu a sprawdzeniem, czy os.path.isdirktoś inny usuwa folder, podniesiesz niewłaściwy, nieaktualny i mylący błąd, że folder istnieje.
farmir

604

Używając try wyjątek i odpowiedni kod błędu z modułu errno pozbywa się warunków wyścigu i działa na różnych platformach:

import os
import errno

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

Innymi słowy, próbujemy utworzyć katalogi, ale jeśli już istnieją, ignorujemy błąd. Z drugiej strony zgłaszany jest każdy inny błąd. Na przykład, jeśli wcześniej utworzysz katalog „a” i usuniesz z niego wszystkie uprawnienia, otrzymasz OSErrorpodwyżkę za pomocą errno.EACCES(Odmowa dostępu, błąd 13).


24
Przyjęta odpowiedź jest w rzeczywistości niebezpieczna, ponieważ ma warunki wyścigowe. Jest to jednak prostsze, więc jeśli nie jesteś świadomy warunków wyścigu lub myślisz, że to cię nie dotyczy, to byłby twój oczywisty pierwszy wybór.
Heikki Toivonen

15
Zgłoszenie wyjątku tylko wtedy exception.errno != errno.EEXIST, gdy przypadkowo zignoruje przypadek, gdy istnieje ścieżka, ale jest to obiekt niebędący katalogiem, taki jak plik. Najlepiej byłoby, gdyby wyjątek został zgłoszony, jeśli ścieżka nie jest katalogiem.
Acumenus,

178
Zauważ, że powyższy kod jest równoważnyos.makedirs(path,exist_ok=True)
Navin

58
@Navin exist_okParametr został wprowadzony w Pythonie 3.2. Nie występuje w Pythonie 2.x. Włączę to do mojej odpowiedzi.
Acumenus

26
@HeikkiToivonen Technicznie rzecz biorąc, jeśli inny program modyfikuje katalogi i pliki w tym samym czasie, co twój program, cały Twój program jest jednym gigantycznym wyścigiem. Co powstrzyma inny program przed usunięciem tego katalogu po utworzeniu go przez kod i przed umieszczeniem w nim plików?
jpmc26

102

Osobiście polecam, abyś użył os.path.isdir()do testowania zamiast 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

Jeśli masz:

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

I głupie dane wejściowe użytkownika:

:: /tmp/dirname/filename.etc

... Skończysz z katalogiem nazwanym, filename.etcgdy przekażesz ten argument, os.makedirs()jeśli testujesz os.path.exists().


8
Jeśli używasz tylko „isdir”, czy nadal nie będziesz mieć problemu przy próbie utworzenia katalogu, a plik o tej samej nazwie już istnieje?
MrWonderful

3
@MrWonderful Wynikający z tego wyjątek podczas tworzenia katalogu na istniejącym pliku poprawnie odzwierciedla problem z powrotem do osoby dzwoniącej.
Damian Yerrick

79

Sprawdź os.makedirs: (upewnia się, że istnieje pełna ścieżka).
Aby obsłużyć fakt, że katalog może istnieć, złap OSError. (Jeśli exist_okjest False(domyślnie), an OSErrorjest podnoszony, jeśli katalog docelowy już istnieje.)

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

19
za pomocą try / wyjątkiem będziesz maskować błędy podczas tworzenia katalogu, w przypadku, gdy katalog nie istniał, ale z jakiegoś powodu nie możesz tego zrobić
Blair Conrad

3
OSErrorzostanie podniesiony tutaj, jeśli ścieżka jest istniejącym plikiem lub katalogiem. Wysłałem odpowiedź, aby rozwiązać ten problem.
Acumenus,

4
To jest w połowie drogi. OSErrorPrzed podjęciem decyzji o zignorowaniu należy sprawdzić warunek błędu podrzędnego . Zobacz stackoverflow.com/a/5032238/763269 .
Chris Johnson

71

Począwszy od Python 3.5, pathlib.Path.mkdirma exist_okflagę:

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

To rekurencyjnie tworzy katalog i nie wywołuje wyjątku, jeśli katalog już istnieje.

(tak jak os.makedirsdostał exist_okflagę zaczynając od python 3.2 np. os.makedirs(path, exist_ok=True))


46

Wgląd w specyfikę tej sytuacji

Dajesz konkretny plik pod określoną ścieżką i wyciągasz katalog ze ścieżki pliku. Następnie po upewnieniu się, że masz katalog, próbujesz otworzyć plik do odczytu. Aby skomentować ten kod:

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

Chcemy uniknąć nadpisywania funkcji wbudowanego, dir. Ponadto, filepatha może fullfilepathjest to prawdopodobnie lepsza nazwa semantyczna, filenamedlatego lepiej byłoby napisać:

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

Twoim ostatecznym celem jest otwarcie tego pliku, początkowo twierdzisz, do pisania, ale zasadniczo zbliżasz się do tego celu (na podstawie twojego kodu) w ten sposób, który otwiera plik do odczytu :

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

Zakładając otwarcie do czytania

Dlaczego miałbyś stworzyć katalog dla pliku, który ma się tam znajdować i być w stanie go odczytać?

Po prostu spróbuj otworzyć plik.

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

Jeśli katalogu lub pliku nie ma, pojawi IOErrorsię powiązany z nim numer błędu: errno.ENOENTwskaże prawidłowy numer błędu niezależnie od platformy. Możesz go złapać, jeśli chcesz, na przykład:

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

Zakładając, że otwieramy się na pisanie

Jest to prawdopodobnie to, czego chce.

W tym przypadku prawdopodobnie nie mamy żadnych warunków wyścigowych. Więc rób tak, jak byłeś, ale pamiętaj, że aby pisać, musisz otworzyć w wtrybie (lub adołączyć). Najlepszą praktyką Pythona jest używanie menedżera kontekstu do otwierania plików.

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

Załóżmy jednak, że mamy kilka procesów w języku Python, które próbują umieścić wszystkie swoje dane w tym samym katalogu. Wtedy możemy mieć spór o utworzenie katalogu. W takim przypadku najlepiej jest zawinąć makedirspołączenie w blok try-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

Wypróbuj os.path.existsfunkcję

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

3
Chciałem skomentować to pytanie, ale czy mamy na myśli os.mkdir? Mój python (2.5.2) nie ma os.path.mkdir ....
Blair Conrad

1
Nie ma os.path.mkdir()metody. Moduł os.path implementuje przydatne funkcje w nazwach ścieżek .
Serge S.

31

Odłożyłem następujące. Nie jest to jednak całkowicie niezawodny.

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

Teraz, jak mówię, nie jest to tak naprawdę niezawodne, ponieważ istnieje możliwość, że nie uda nam się utworzyć katalogu i innego procesu, który go utworzy w tym okresie.



Dwa problemy: (1) musisz sprawdzić warunek błędu podrzędnego OSError przed podjęciem decyzji o sprawdzeniu os.path.exists- patrz stackoverflow.com/a/5032238/763269, i (2) powodzenie os.path.existsnie oznacza, że ​​katalog istnieje, tylko że ścieżka istnieje - może to być plik, dowiązanie symboliczne lub inny obiekt systemu plików.
Chris Johnson

24

Sprawdź, czy katalog istnieje i utwórz go, jeśli to konieczne?

Bezpośrednią odpowiedzią na to jest założenie prostej sytuacji, w której nie spodziewasz się, że inni użytkownicy lub procesy będą bałagać się w twoim katalogu:

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

lub jeśli utworzenie katalogu podlega warunkom wyścigu (tj. jeśli po sprawdzeniu ścieżki istnieje, coś innego mogło już to zrobić):

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

Być może jednak jeszcze lepszym rozwiązaniem jest ominięcie problemu rywalizacji o zasoby za pomocą katalogów tymczasowych poprzez tempfile:

import tempfile

d = tempfile.mkdtemp()

Oto najważniejsze informacje z dokumentu online:

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.

Nowości w Python 3.5: pathlib.Pathzexist_ok

Jest nowy Pathobiekt (od wersji 3.4) z wieloma metodami, których chcielibyśmy używać ze ścieżkami - jedną z nich jestmkdir .

(Dla kontekstu śledzę mojego cotygodniowego przedstawiciela za pomocą skryptu. Oto odpowiednie części kodu ze skryptu, które pozwalają mi uniknąć uderzenia przepełnienia stosu więcej niż raz dziennie dla tych samych danych.)

Najpierw odpowiedni przywóz:

from pathlib import Path
import tempfile

Nie musimy się os.path.jointeraz zajmować - po prostu połącz części ścieżki za pomocą /:

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

Następnie idempotentnie upewniam się, że katalog istnieje - exist_okargument pojawia się w Pythonie 3.5:

directory.mkdir(exist_ok=True)

Oto odpowiednia część dokumentacji :

Jeśli exist_okjest to prawda, FileExistsErrorwyjątki zostaną zignorowane (to samo zachowanie, co POSIX mkdir -ppolecenie), ale tylko wtedy, gdy ostatni element ścieżki nie jest istniejącym plikiem spoza katalogu.

Oto trochę więcej skryptu - w moim przypadku nie podlegam warunkom wyścigowym, mam tylko jeden proces, który oczekuje, że katalog (lub zawarte pliki) tam będzie, i nie mam nic, co próbuje usunąć katalog.

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))

Pathobiekty muszą zostać wymuszone, strzanim inne interfejsy API oczekujące strścieżek będą mogły ich używać.

Może Pandy powinny być aktualizowane, aby zaakceptować wystąpień abstrakcyjnej klasy bazowej os.PathLike.


20

W Pythonie 3.4 możesz także użyć zupełnie nowego pathlibmodułu :

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 jest nowszym backportem. Starszy jest nieobsługiwany.
Acumenus,

Jak stwierdzono w pierwszym wierszu readme; P. Ale stary backport jest nadal ważny dla odpowiedzi tutaj. I nie ma nazywania bólu głowy. Nie trzeba wyjaśniać, dlaczego i kiedy używać pathlibi gdzie pathlib2dla nowych użytkowników, i myślę, że profesjonaliści tutaj dowiedzą się o wycofaniu;)
Janusz Skonieczny

13

Odpowiedniej dokumentacji Python sugeruje zastosowanie EAFP styl kodowania (łatwiej jest prosić o przebaczenie niż uprawnienia) . Oznacza to, że kod

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

jest lepszy niż alternatywa

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

Dokumentacja sugeruje to właśnie ze względu na warunki wyścigu omówione w tym pytaniu. Ponadto, jak wspominają inni, przewaga kwerendy w stosunku do jednego systemu operacyjnego jest większa. Wreszcie argument wysunięty potencjalnie na korzyść drugiego kodu w niektórych przypadkach - gdy programista zna środowisko, w którym działa aplikacja - może być popierany tylko w szczególnym przypadku, w którym program skonfigurował środowisko prywatne dla sam (i inne wystąpienia tego samego programu).

Nawet w takim przypadku jest to zła praktyka i może prowadzić do długiego bezużytecznego debugowania. Na przykład fakt, że ustawiamy uprawnienia do katalogu, nie powinien pozostawiać nas z uprawnieniami do wyświetlania są odpowiednio ustawione dla naszych celów. Katalog nadrzędny można podłączyć z innymi uprawnieniami. Zasadniczo program powinien zawsze działać poprawnie, a programista nie powinien oczekiwać jednego określonego środowiska.


11

W Python3 , os.makedirsustawienie podpory exist_ok. Ustawieniem domyślnym jest False, co oznacza, że OSErrorzostanie podniesiony, jeśli katalog docelowy już istnieje. Ustawiając exist_oksię True, OSError(istnieje katalog) będą ignorowane i katalog nie zostanie utworzony.

os.makedirs(path,exist_ok=True)

W python2 , os.makedirsnie obsługuje ustawienia exist_ok. Możesz użyć tego podejścia w odpowiedzi 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

W przypadku rozwiązania jednowarstwowego możesz użyć IPython.utils.path.ensure_dir_exists():

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

Z dokumentacji : Upewnij się, że istnieje katalog. Jeśli nie istnieje, spróbuj go utworzyć i zabezpieczyć przed warunkami wyścigu, jeśli robi to inny proces.


Nowa dokumentacja IPython dostępna tutaj .
jkdev,

3
Nie IPythonma gwarancji, że moduł będzie obecny. Jest natywnie obecny na moim Macu, ale nie na żadnej z moich instalacji Linuksa w Pythonie. Zasadniczo nie jest to jeden z modułów wymienionych w indeksie modułów Pythona .
Acumenus

1
Pewnie. Aby zainstalować pakiet, wystarczy uruchomić zwykły pip install ipythonlub zawierać zależność w swoim requirements.txt lub pom.xml . Dokumentacja: ipython.org/install.html
tashuhka

9

Możesz użyć mkpath

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

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

Pamiętaj, że utworzy także katalogi przodków.

Działa dla Python 2 i 3.


2
distutils.dir_utilnie jest częścią publicznego interfejsu API distutil i ma problemy w środowiskach wielowątkowych: bugs.python.org/issue10948
Pod

1
Tak. Jak zauważono w pierwszej wiadomości o błędzie, problem distutils.dir_util.mkpathpolega na tym, że jeśli utworzysz katalog, a następnie usuniesz go z wnętrza lub z zewnątrz Pythona, a następnie użyjesz mkpathponownie, mkpathpo prostu użyje swoich niepoprawnych informacji z pamięci podręcznej o wcześniejszym utworzeniu katalogu i będzie nie tworzy ponownie katalogu. W przeciwieństwie do tego, os.makedirsnie polega na takiej pamięci podręcznej.
Acumenus

8

Używam os.path.exists(), oto skrypt w języku Python 3, którego można użyć do sprawdzenia, czy katalog istnieje, utwórz go, jeśli nie istnieje, i usuń, jeśli istnieje (w razie potrzeby).

Monituje użytkowników o wprowadzenie katalogu i może być łatwo modyfikowany.


6

Możesz użyć os.listdirdo tego:

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

To nie odpowiada na pytanie
Georgy

6

Znalazłem to pytanie i początkowo byłem zaskoczony niektórymi błędami i błędami, które otrzymywałem. Pracuję w Pythonie 3 (v.3.5 w środowisku wirtualnym Anaconda w systemie Arch Linux x86_64).

Rozważ tę strukturę katalogów:

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

Oto moje eksperymenty / notatki, które wyjaśniają rzeczy:

# ----------------------------------------------------------------------------
# [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
# ----------------------------------------------------------------------------

Wniosek: moim zdaniem „metoda 2” jest bardziej niezawodna.

[1] Jak mogę utworzyć katalog, jeśli nie istnieje?

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


6

Zobaczyłem odpowiedzi Heikki Toivonen i ABB i pomyślałem o tej odmianie.

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

Dlaczego nie użyć modułu podprocesu, jeśli działa na komputerze obsługującym polecenie mkdirz -popcją? Działa na Python 2.7 i Python 3.6

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

Powinien załatwić sprawę w większości systemów.

W sytuacjach, w których przenośność nie ma znaczenia (np. Przy użyciu dokera) rozwiązaniem są czyste 2 linie. Nie musisz także dodawać logiki, aby sprawdzić, czy katalogi istnieją, czy nie. Wreszcie, można bezpiecznie uruchomić ponownie bez żadnych skutków ubocznych

Jeśli potrzebujesz obsługi błędów:

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

4

Jeśli weźmiesz pod uwagę następujące kwestie:

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

oznacza, że ​​istnieje katalog (ścieżka) AND to katalog. Więc dla mnie w ten sposób robi to, czego potrzebuję. Mogę więc upewnić się, że jest to folder (a nie plik) i że istnieje.


Jak to odpowiada na pytanie dotyczące utworzenia katalogu?
Georgy

3

Wywołaj funkcję create_dir()w punkcie wejścia programu / projektu.

import os

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

create_dir('Project directory')

3

Musisz ustawić pełną ścieżkę przed utworzeniem katalogu:

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)

To działa dla mnie i mam nadzieję, że zadziała również dla ciebie


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

Tam, gdzie jest twój kod, użyj polecenia (dotknij)

Spowoduje to sprawdzenie, czy plik istnieje, jeśli go nie ma, to go utworzy.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.