Wie kann ich sicher ein verschachteltes Verzeichnis erstellen?


4247

Was ist die eleganteste Methode, um zu überprüfen, ob das Verzeichnis, in das eine Datei geschrieben werden soll, vorhanden ist, und wenn nicht, erstellen Sie das Verzeichnis mit Python? Folgendes habe ich versucht:

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)

Irgendwie habe ich es vermisst os.path.exists(danke Kanja, Blair und Douglas). Das habe ich jetzt:

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

Gibt es eine Flagge für "offen", die dies automatisch ermöglicht?


27
Im Allgemeinen müssen Sie möglicherweise den Fall berücksichtigen, dass der Dateiname kein Verzeichnis enthält. Auf meinem Computer gibt dirname ('foo.txt') '' an, was nicht existiert und dazu führt, dass makedirs () fehlschlägt.
Brian Hawkins

11
In Python 2.7 os.path.mkdirexistiert nicht. Es ist os.mkdir.
Drevicko

6
Wenn der Pfad existiert, muss man nicht nur überprüfen, ob es sich um ein Verzeichnis und nicht um eine reguläre Datei oder ein anderes Objekt handelt (viele Antworten überprüfen dies). Es muss auch überprüft werden, ob er beschreibbar ist (ich habe keine Antwort gefunden, die dies überprüft hat).
Wunder173

9
Für den Fall, dass Sie hierher gekommen sind, um übergeordnete Verzeichnisse der Dateipfadzeichenfolge zu erstellen p, ist hier mein Codefragment:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
Thamme Gowda

Antworten:


5190

Verwenden Sie unter Python ≥ 3.5 pathlib.Path.mkdir:

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

Für ältere Versionen von Python sehe ich zwei Antworten mit guten Eigenschaften, jede mit einem kleinen Fehler, also werde ich meine Meinung dazu abgeben:

Versuchen Sie es os.path.existsund überlegen Sie es sich os.makedirsfür die Erstellung.

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

Wie in Kommentaren und an anderer Stelle erwähnt, gibt es eine Race-Bedingung - wenn das Verzeichnis zwischen dem os.path.existsund dem os.makedirsAufruf erstellt os.makedirswird, schlägt das mit einem fehl OSError. Leider ist das Abfangen OSErrorund Fortfahren von Decken nicht kinderleicht, da ein Fehler beim Erstellen des Verzeichnisses aufgrund anderer Faktoren wie unzureichender Berechtigungen, vollständiger Festplatte usw. ignoriert wird.

Eine Möglichkeit wäre OSError, den eingebetteten Fehlercode abzufangen und zu untersuchen (siehe Gibt es eine plattformübergreifende Möglichkeit, Informationen von Pythons OSError abzurufen ):

import os, errno

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

Alternativ könnte es eine Sekunde geben os.path.exists, aber nehmen wir an, eine andere hat das Verzeichnis nach der ersten Überprüfung erstellt und es dann vor der zweiten entfernt - wir könnten uns immer noch täuschen lassen.

Abhängig von der Anwendung kann die Gefahr gleichzeitiger Vorgänge mehr oder weniger groß sein als die Gefahr, die durch andere Faktoren wie z. B. Dateiberechtigungen entsteht. Der Entwickler müsste mehr über die jeweilige zu entwickelnde Anwendung und die erwartete Umgebung wissen, bevor er eine Implementierung auswählt.

Moderne Versionen von Python verbessern diesen Code erheblich, indem sie FileExistsError(in 3.3 +) ...

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

... und indem ein Schlüsselwortargument os.makedirsaufgerufen wirdexist_ok (in 3.2+).

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

5
Die Race-Bedingung ist ein guter Punkt, aber der Ansatz in stackoverflow.com/questions/273192/#273208 maskiert einen Fehler beim Erstellen des Verzeichnisses. Fühlen Sie sich nicht schlecht, wenn Sie abstimmen - die Antwort gefällt Ihnen nicht. Dafür sind Stimmen da.
Blair Conrad

27
Denken Sie daran, dass os.path.exists () nicht kostenlos ist. Wenn der Normalfall darin besteht, dass das Verzeichnis vorhanden ist, sollte der Fall, in dem dies nicht der Fall ist, als Ausnahme behandelt werden. Mit anderen Worten, versuchen Sie, Ihre Datei zu öffnen und in sie zu schreiben, die OSError-Ausnahme abzufangen und basierend auf errno makedir () auszuführen und erneut zu versuchen oder erneut zu erhöhen. Dies führt zu einer Duplizierung des Codes, sofern Sie das Schreiben nicht in eine lokale Methode einschließen.
Andrew

22
os.path.existsGibt auch Truefür eine Datei zurück. Ich habe eine Antwort gepostet, um dies zu beheben.
Acumenus

13
Wie Kommentatoren zu anderen Antworten hier angemerkt haben, kann der exists_okParameter to os.makedirs()verwendet werden, um zu behandeln, wie das vorherige Vorhandensein des Pfads seit Python 3.2 behandelt wird.
Bobble

6
os.mkdirs()kann unbeabsichtigte Ordner erstellen, wenn ein Pfadtrennzeichen versehentlich weggelassen wird, der aktuelle Ordner nicht wie erwartet ist und ein Pfadelement das Pfadtrennzeichen enthält. Wenn Sie os.mkdir()diese Fehler verwenden, wird eine Ausnahme ausgelöst, die Sie auf ihre Existenz hinweist.
Drevicko

1241

Python 3.5+:

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

pathlib.Path.mkdirWie oben verwendet, wird das Verzeichnis rekursiv erstellt und es wird keine Ausnahme ausgelöst, wenn das Verzeichnis bereits vorhanden ist. Wenn Sie nicht möchten oder möchten, dass die Eltern erstellt werden, überspringen Sie das parentsArgument.

Python 3.2+:

Verwenden von pathlib:

Wenn Sie können, installieren Sie den aktuellen pathlibBackport mit dem Namen pathlib2. Installieren Sie nicht den älteren nicht gepflegten Backport mit dem Namen pathlib. Lesen Sie als Nächstes den obigen Abschnitt zu Python 3.5+ und verwenden Sie ihn auf dieselbe Weise.

Wenn Sie Python 3.4 verwenden, pathlibfehlt die nützliche exist_okOption , obwohl es mitgeliefert wird. Der Backport soll eine neuere und überlegenere Implementierung bieten, mkdirdie diese fehlende Option enthält.

Verwenden von os:

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

os.makedirsWie oben verwendet, wird das Verzeichnis rekursiv erstellt und es wird keine Ausnahme ausgelöst, wenn das Verzeichnis bereits vorhanden ist. Es hat nur das optionale exist_okArgument, wenn Python 3.2+ mit dem Standardwert von verwendet wird False. Dieses Argument existiert in Python 2.x bis 2.7 nicht. Daher ist keine manuelle Ausnahmebehandlung wie bei Python 2.7 erforderlich.

Python 2.7+:

Verwenden von pathlib:

Wenn Sie können, installieren Sie den aktuellen pathlibBackport mit dem Namen pathlib2. Installieren Sie nicht den älteren nicht gepflegten Backport mit dem Namen pathlib. Lesen Sie als Nächstes den obigen Abschnitt zu Python 3.5+ und verwenden Sie ihn auf dieselbe Weise.

Verwenden von os:

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

Während eine naive Lösung zuerst verwendet werden kann, os.path.isdirgefolgt von os.makedirsder obigen Lösung, kehrt die obige Lösung die Reihenfolge der beiden Operationen um. Auf diese Weise wird verhindert, dass eine häufige Racebedingung mit einem doppelten Versuch zum Erstellen des Verzeichnisses zu tun hat, und es werden auch Dateien aus Verzeichnissen eindeutig.

Beachten Sie, dass die Ausnahme der Erfassung und Verwendung errnovon begrenztem Nutzen ist , weil OSError: [Errno 17] File exists, das heißt errno.EEXIST, erhöht wird , sowohl für Dateien und Verzeichnisse. Es ist zuverlässiger, einfach zu überprüfen, ob das Verzeichnis vorhanden ist.

Alternative:

mkpathErstellt das verschachtelte Verzeichnis und führt nichts aus, wenn das Verzeichnis bereits vorhanden ist. Dies funktioniert sowohl in Python 2 als auch in Python 3.

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

Per Bug 10948 , ist eine schwere Einschränkung dieser Alternative , dass es nur einmal pro Python - Prozess für einen bestimmten Pfad funktioniert. Mit anderen Worten, wenn Sie es zum Erstellen eines Verzeichnisses verwenden, dann das Verzeichnis innerhalb oder außerhalb von Python löschen und dann mkpatherneut verwenden, um dasselbe Verzeichnis neu zu erstellen, mkpathwerden einfach die ungültigen zwischengespeicherten Informationen verwendet, die das Verzeichnis zuvor erstellt haben, und nicht mache das Verzeichnis tatsächlich wieder. Im Gegensatz dazu ist os.makedirskein solcher Cache erforderlich. Diese Einschränkung kann für einige Anwendungen in Ordnung sein.


Informationen zum Modus des Verzeichnisses finden Sie in der Dokumentation, wenn Sie sich dafür interessieren.


13
Diese Antwort deckt so ziemlich jeden Sonderfall ab, soweit ich das beurteilen kann. Ich habe vor, dies in ein "wenn nicht os.path.isdir ()" zu verpacken, da ich davon ausgehe, dass das Verzeichnis fast jedes Mal existiert und ich die Ausnahme auf diese Weise vermeiden kann.
Charles L.

5
@ CharlesL. Eine Ausnahme ist wahrscheinlich billiger als die Festplatten-E / A der Prüfung, wenn Ihr Grund die Leistung ist.
jpmc26

1
@ jpmc26 aber makedirs führt zusätzliche stat, umask, lstat aus, wenn nur überprüft wird, ob OSError ausgelöst wird.
kwarunek

4
Dies ist die falsche Antwort, da dadurch eine potenzielle FS-Rennbedingung eingeführt wird. Siehe Antwort von Aaron Hall.
Sleepycal

4
Wie @sleepycal gesagt hat, leidet dies unter einer ähnlichen Rennbedingung wie die akzeptierte Antwort. Wenn zwischen dem Auslösen des Fehlers und dem Überprüfen os.path.isdir, ob jemand anderes den Ordner löscht, der falsche, veraltete und verwirrende Fehler dieses Ordners auftritt.
Farmir

604

Die Verwendung von try Except und des richtigen Fehlercodes vom errno-Modul beseitigt die Rennbedingung und ist plattformübergreifend:

import os
import errno

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

Mit anderen Worten, wir versuchen, die Verzeichnisse zu erstellen, aber wenn sie bereits vorhanden sind, ignorieren wir den Fehler. Andererseits wird jeder andere Fehler gemeldet. Wenn Sie beispielsweise zuvor das Verzeichnis 'a' erstellen und alle Berechtigungen daraus entfernen, wird eine OSErrorErhöhung mit errno.EACCES(Berechtigung verweigert, Fehler 13) angezeigt.


24
Die akzeptierte Antwort ist tatsächlich gefährlich, weil sie eine Rennbedingung hat. Es ist jedoch einfacher. Wenn Sie sich der Rennbedingungen nicht bewusst sind oder der Meinung sind, dass sie nicht auf Sie zutreffen, ist dies Ihre offensichtliche erste Wahl.
Heikki Toivonen

15
Das Auslösen der Ausnahme nur dann, wenn exception.errno != errno.EEXISTder Fall unbeabsichtigt ignoriert wird, wenn der Pfad vorhanden ist, es sich jedoch um ein Nicht-Verzeichnisobjekt wie eine Datei handelt. Die Ausnahme sollte idealerweise ausgelöst werden, wenn der Pfad ein Nicht-Verzeichnisobjekt ist.
Acumenus

178
Beachten Sie, dass der obige Code äquivalent zuos.makedirs(path,exist_ok=True)
Navin

58
@Navin Der exist_okParameter wurde in Python 3.2 eingeführt. Es ist in Python 2.x nicht vorhanden. Ich werde es in meine Antwort aufnehmen.
Acumenus

26
@HeikkiToivonen Technisch gesehen ist Ihr gesamtes Programm eine riesige Rennbedingung, wenn ein anderes Programm die Verzeichnisse und Dateien gleichzeitig mit Ihrem Programm ändert. Was hindert ein anderes Programm daran, dieses Verzeichnis nur zu löschen, nachdem der Code es erstellt hat und bevor Sie tatsächlich Dateien darin ablegen?
jpmc26

102

Ich würde Ihnen persönlich empfehlen, statt os.path.isdir()zu testen 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

Wenn Sie haben:

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

Und eine dumme Benutzereingabe:

:: /tmp/dirname/filename.etc

... Sie erhalten ein Verzeichnis mit dem Namen, filename.etcwenn Sie dieses Argument an übergeben, os.makedirs()wenn Sie mit testen os.path.exists().


8
Wenn Sie nur 'isdir' verwenden, haben Sie dann nicht immer noch ein Problem, wenn Sie versuchen, das Verzeichnis zu erstellen, und eine Datei mit demselben Namen bereits vorhanden ist?
MrWonderful

3
@MrWonderful Die resultierende Ausnahme beim Erstellen eines Verzeichnisses über einer vorhandenen Datei würde das Problem korrekt an den Aufrufer zurückgeben.
Damian Yerrick

79

Überprüfen Sie os.makedirs: (Es stellt sicher, dass der vollständige Pfad vorhanden ist.)
Um die Tatsache zu behandeln, dass das Verzeichnis möglicherweise vorhanden ist, fangen Sie ab OSError. (If exist_okis False(Standardeinstellung) OSErrorwird ausgelöst, wenn das Zielverzeichnis bereits vorhanden ist.)

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

19
Mit dem Versuch / Ausnahme werden Sie Fehler bei der Verzeichniserstellung maskieren, falls das Verzeichnis nicht vorhanden war, Sie es aber aus irgendeinem Grund nicht schaffen können
Blair Conrad

3
OSErrorwird hier ausgelöst, wenn der Pfad eine vorhandene Datei oder ein vorhandenes Verzeichnis ist. Ich habe eine Antwort gepostet, um dies zu beheben.
Acumenus

4
Das ist auf halbem Weg. Sie müssen den Unterfehlerzustand von überprüfen, OSErrorbevor Sie ihn ignorieren. Siehe stackoverflow.com/a/5032238/763269 .
Chris Johnson

71

Ab Python 3.5 pathlib.Path.mkdirhat eine exist_okFlagge:

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

Dadurch wird das Verzeichnis rekursiv erstellt und keine Ausnahme ausgelöst, wenn das Verzeichnis bereits vorhanden ist.

(genau wie os.makedirseine exist_okFlagge ab Python 3.2 zB os.makedirs(path, exist_ok=True))


46

Einblicke in die Besonderheiten dieser Situation

Sie geben eine bestimmte Datei unter einem bestimmten Pfad an und ziehen das Verzeichnis aus dem Dateipfad. Nachdem Sie sichergestellt haben, dass Sie über das Verzeichnis verfügen, versuchen Sie, eine Datei zum Lesen zu öffnen. So kommentieren Sie diesen Code:

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

Wir möchten vermeiden, die eingebaute Funktion zu überschreiben dir. Auch, filepathoder vielleicht fullfilepathist wahrscheinlich ein besserer semantischer Name als filenameso wäre dies besser geschrieben:

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

Ihr Endziel ist es, diese Datei zum Schreiben zu öffnen, aber Sie nähern sich diesem Ziel (basierend auf Ihrem Code) im Wesentlichen wie folgt, wodurch die Datei zum Lesen geöffnet wird :

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

Angenommen, Öffnung zum Lesen

Warum sollten Sie ein Verzeichnis für eine Datei erstellen, von der Sie erwarten, dass sie dort ist und gelesen werden kann?

Versuchen Sie einfach, die Datei zu öffnen.

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

Wenn das Verzeichnis oder die Datei nicht vorhanden ist, erhalten Sie eine IOErrormit einer zugehörigen Fehlernummer: Zeigt errno.ENOENTunabhängig von Ihrer Plattform auf die richtige Fehlernummer. Sie können es fangen, wenn Sie wollen, zum Beispiel:

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

Angenommen, wir öffnen uns zum Schreiben

Dies ist wahrscheinlich, was Sie wollen.

In diesem Fall haben wir wahrscheinlich keine Rennbedingungen. Tun Sie einfach so, wie Sie es waren, aber beachten Sie, dass Sie zum Schreiben mit dem wModus öffnen (oder aanhängen) müssen. Es ist auch eine bewährte Python-Methode, den Kontextmanager zum Öffnen von Dateien zu verwenden.

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

Angenommen, wir haben mehrere Python-Prozesse, die versuchen, alle ihre Daten in dasselbe Verzeichnis zu stellen. Dann haben wir möglicherweise Streit um die Erstellung des Verzeichnisses. In diesem Fall ist es am besten, den makedirsAufruf in einen Try-Except-Block zu packen.

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

Probieren Sie die os.path.existsFunktion aus

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

3
Ich wollte die Frage kommentieren, aber meinen wir os.mkdir? Meine Python (2.5.2) hat keine os.path.mkdir ....
Blair Conrad

1
Es gibt keine os.path.mkdir()Methode. Das Modul os.path implementiert einige nützliche Funktionen für Pfadnamen .
Serge S.

31

Ich habe folgendes niedergeschrieben. Es ist jedoch nicht absolut narrensicher.

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

Wie ich bereits sagte, ist dies nicht wirklich narrensicher, da wir möglicherweise das Verzeichnis und einen anderen Prozess, der es in dieser Zeit erstellt, nicht erstellen können.



Zwei Probleme: (1) Sie müssen den Unterfehlerzustand von OSError überprüfen, bevor Sie sich für eine Überprüfung entscheiden os.path.exists- siehe stackoverflow.com/a/5032238/763269. (2) Erfolg os.path.existsbedeutet nicht, dass das Verzeichnis vorhanden ist, sondern nur, dass der Pfad vorhanden ist existiert - kann eine Datei, ein Symlink oder ein anderes Dateisystemobjekt sein.
Chris Johnson

24

Überprüfen Sie, ob ein Verzeichnis vorhanden ist, und erstellen Sie es gegebenenfalls?

Die direkte Antwort darauf lautet unter der Annahme einer einfachen Situation, in der Sie nicht erwarten, dass andere Benutzer oder Prozesse mit Ihrem Verzeichnis herumspielen:

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

oder wenn das Erstellen des Verzeichnisses den Rennbedingungen unterliegt (dh wenn nach Überprüfung des vorhandenen Pfads bereits etwas anderes erstellt wurde), gehen Sie folgendermaßen vor:

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

Ein vielleicht noch besserer Ansatz besteht darin, das Problem der Ressourcenkonflikte zu umgehen, indem temporäre Verzeichnisse über Folgendes verwendet werden tempfile:

import tempfile

d = tempfile.mkdtemp()

Hier sind die wichtigsten Informationen aus dem Online-Dokument:

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.

Neu in Python 3.5: pathlib.Pathmitexist_ok

Es gibt ein neues PathObjekt (ab 3.4) mit vielen Methoden, die man mit Pfaden verwenden möchte - eine davon ist mkdir.

(Für den Kontext verfolge ich meine wöchentliche Wiederholung mit einem Skript. Hier sind die relevanten Teile des Codes aus dem Skript, mit denen ich vermeiden kann, mehr als einmal am Tag auf den Stapelüberlauf für dieselben Daten zu stoßen.)

Zunächst die relevanten Importe:

from pathlib import Path
import tempfile

Wir müssen uns jetzt nicht darum kümmern os.path.join- verbinden Sie einfach Pfadteile mit einem /:

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

Dann stelle ich idempotent sicher, dass das Verzeichnis existiert - das exist_okArgument wird in Python 3.5 angezeigt:

directory.mkdir(exist_ok=True)

Hier ist der relevante Teil der Dokumentation :

Wenn dies der exist_okFall ist, werden FileExistsErrorAusnahmen ignoriert (dasselbe Verhalten wie beim POSIX mkdir -pBefehl), jedoch nur, wenn die letzte Pfadkomponente keine vorhandene Nichtverzeichnisdatei ist.

Hier ist ein wenig mehr vom Skript - in meinem Fall unterliegt ich keiner Race-Bedingung, ich habe nur einen Prozess, der erwartet, dass das Verzeichnis (oder die enthaltenen Dateien) vorhanden ist, und ich habe nichts, was versucht, es zu entfernen das Verzeichnis.

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

PathObjekte müssen erzwungen werden, strbevor andere APIs, die strPfade erwarten, sie verwenden können.

Vielleicht sollten Pandas aktualisiert werden, um Instanzen der abstrakten Basisklasse zu akzeptieren os.PathLike.


20

In Python 3.4 können Sie auch das brandneue pathlibModul verwenden :

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 ist der neuere Backport. Der ältere ist nicht gepflegt.
Acumenus

Wie es in der ersten Zeile der Readme heißt; P. Der alte Backport gilt jedoch weiterhin für die Antwort hier. Und es gibt keine Namenskopfschmerzen. Keine Notwendigkeit zu erklären, warum und wann pathlibund wo pathlib2für die neuen Benutzer zu verwenden, und ich denke, Profis hier werden die Abwertung herausfinden;)
Janusz Skonieczny

13

In der entsprechenden Python-Dokumentation wird die Verwendung des EAFP-Codierungsstils vorgeschlagen (einfacher um Vergebung zu bitten als um Erlaubnis) . Dies bedeutet, dass der Code

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

ist besser als die Alternative

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

Die Dokumentation schlägt dies genau aufgrund der in dieser Frage diskutierten Rennbedingungen vor. Darüber hinaus gibt es, wie andere hier erwähnen, einen Leistungsvorteil, wenn das Betriebssystem einmal statt zweimal abgefragt wird. Schließlich kann das Argument, das in einigen Fällen möglicherweise zugunsten des zweiten Codes vorgebracht wird - wenn der Entwickler die Umgebung kennt, in der die Anwendung ausgeführt wird - nur in dem speziellen Fall vertreten werden, für den das Programm eine private Umgebung eingerichtet hat selbst (und andere Instanzen desselben Programms).

Selbst in diesem Fall ist dies eine schlechte Praxis und kann zu langem, nutzlosem Debuggen führen. Zum Beispiel sollte die Tatsache, dass wir die Berechtigungen für ein Verzeichnis festlegen, nicht dazu führen, dass die Impression-Berechtigungen für unsere Zwecke entsprechend festgelegt werden. Ein übergeordnetes Verzeichnis kann mit anderen Berechtigungen bereitgestellt werden. Im Allgemeinen sollte ein Programm immer korrekt funktionieren und der Programmierer sollte keine bestimmte Umgebung erwarten.


11

In Python3 , os.makedirsEinstellung unterstützt exist_ok. Die Standardeinstellung ist False, was bedeutet, dass ein OSErrorausgelöst wird, wenn das Zielverzeichnis bereits vorhanden ist. Durch die Einstellung exist_okauf True, OSError(Verzeichnis vorhanden ist ) wird ignoriert und das Verzeichnis wird nicht erstellt werden.

os.makedirs(path,exist_ok=True)

In Python2 wird os.makedirsdie Einstellung nicht unterstützt exist_ok. Sie können den Ansatz in der Antwort von heikki-toivonen verwenden :

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

Für eine Einzeilerlösung können Sie Folgendes verwenden IPython.utils.path.ensure_dir_exists():

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

Aus der Dokumentation : Stellen Sie sicher, dass ein Verzeichnis vorhanden ist. Wenn es nicht existiert, versuchen Sie es zu erstellen und vor einer Racebedingung zu schützen, wenn ein anderer Prozess dasselbe tut.


Neue IPython-Dokumentation finden Sie hier .
jkdev

3
Es IPythonist absolut nicht garantiert, dass das Modul vorhanden ist. Es ist nativ auf meinem Mac vorhanden, aber nicht auf einer meiner Linux-Installationen von Python. Grundsätzlich ist es nicht eines der im Python-Modulindex aufgeführten Module .
Acumenus

1
Sicher. Um das Paket zu installieren, führen Sie einfach das Übliche aus pip install ipythonoder fügen Sie die Abhängigkeit in Ihre Anforderungen.txt oder pom.xml ein . Dokumentation: ipython.org/install.html
Tashuhka

9

Sie können verwenden mkpath

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

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

Beachten Sie, dass auch die Ahnenverzeichnisse erstellt werden.

Es funktioniert für Python 2 und 3.


2
distutils.dir_utilist kein Teil der distutil public API und hat Probleme in Umgebungen mit mehreren Threads: bugs.python.org/issue10948
Pod

1
Ja. Wie in der ersten Meldung des Fehlers erwähnt, besteht das Problem distutils.dir_util.mkpathdarin, dass, wenn Sie ein Verzeichnis erstellen, es dann innerhalb oder außerhalb von Python löschen und dann mkpatherneut verwenden, mkpatheinfach die ungültigen zwischengespeicherten Informationen verwendet werden, die das Verzeichnis zuvor erstellt haben, und dies auch tun wird nicht wirklich das Verzeichnis wieder machen. Im Gegensatz dazu ist os.makedirskein solcher Cache erforderlich.
Acumenus

8

Ich benutze os.path.exists(), hier ist ein Python 3-Skript, mit dem überprüft werden kann, ob ein Verzeichnis vorhanden ist, eines erstellt wird, wenn es nicht vorhanden ist, und es gelöscht werden kann, wenn es vorhanden ist (falls gewünscht).

Es fordert Benutzer zur Eingabe des Verzeichnisses auf und kann leicht geändert werden.


6

Sie können dafür verwenden os.listdir:

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

Dies beantwortet nicht die Frage
Georgy

6

Ich fand diese Frage und Antwort und war anfangs verwirrt über einige der Fehler, die ich bekam. Ich arbeite in Python 3 (v.3.5 in einer virtuellen Anaconda-Umgebung auf einem Arch Linux x86_64-System).

Betrachten Sie diese Verzeichnisstruktur:

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

Hier sind meine Experimente / Notizen, die die Dinge klarstellen:

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

Fazit: Meiner Meinung nach ist "Methode 2" robuster.

[1] Wie kann ich ein Verzeichnis erstellen, wenn es nicht existiert?

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


6

Ich sah die Antworten von Heikki Toivonen und ABB und dachte an diese Variante.

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

6

Verwenden Sie diese Befehlsprüfung und erstellen Sie ein Verzeichnis

 if not os.path.isdir(test_img_dir):
     os.mkdir(test_img_dir)

5

Warum nicht das Unterprozessmodul verwenden, wenn es auf einem Computer ausgeführt wird, der Befehle mkdirmit -pOption unterstützt? Funktioniert mit Python 2.7 und Python 3.6

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

Sollte auf den meisten Systemen den Trick machen.

In Situationen, in denen die Portabilität keine Rolle spielt (z. B. mit Docker), besteht die Lösung aus sauberen 2 Zeilen. Sie müssen auch keine Logik hinzufügen, um zu überprüfen, ob Verzeichnisse vorhanden sind oder nicht. Schließlich ist es sicher, ohne Nebenwirkungen erneut zu starten

Wenn Sie eine Fehlerbehandlung benötigen:

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

4

Wenn Sie Folgendes berücksichtigen:

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

bedeutet, dass ein Verzeichnis (Pfad) existiert UND ein Verzeichnis ist. Für mich macht dieser Weg also das, was ich brauche. So kann ich sicherstellen, dass es sich um einen Ordner (keine Datei) handelt und existiert.


Wie beantwortet dies eine Frage zum Erstellen eines Verzeichnisses?
Georgy

3

Rufen Sie die Funktion create_dir()am Einstiegspunkt Ihres Programms / Projekts auf.

import os

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

create_dir('Project directory')

3

Sie müssen den vollständigen Pfad festlegen, bevor Sie das Verzeichnis erstellen:

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)

Das funktioniert bei mir und hoffentlich auch bei Ihnen


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

Wo sich Ihr Code hier befindet, verwenden Sie den Befehl (touch)

Dadurch wird überprüft, ob die Datei vorhanden ist. Wenn dies nicht der Fall ist, wird sie erstellt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.