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?
os.path.mkdir
existiert nicht. Es istos.mkdir
.p
, ist hier mein Codefragment:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
Antworten:
Verwenden Sie unter Python ≥ 3.5
pathlib.Path.mkdir
: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.exists
und überlegen Sie es sichos.makedirs
für die Erstellung.Wie in Kommentaren und an anderer Stelle erwähnt, gibt es eine Race-Bedingung - wenn das Verzeichnis zwischen dem
os.path.exists
und demos.makedirs
Aufruf erstelltos.makedirs
wird, schlägt das mit einem fehlOSError
. Leider ist das AbfangenOSError
und 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 ):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 +) ...... und indem ein Schlüsselwortargument
os.makedirs
aufgerufen wirdexist_ok
(in 3.2+).quelle
os.path.exists
Gibt auchTrue
für eine Datei zurück. Ich habe eine Antwort gepostet, um dies zu beheben.exists_ok
Parameter toos.makedirs()
verwendet werden, um zu behandeln, wie das vorherige Vorhandensein des Pfads seit Python 3.2 behandelt wird.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 Sieos.mkdir()
diese Fehler verwenden, wird eine Ausnahme ausgelöst, die Sie auf ihre Existenz hinweist.Python 3.5+:
pathlib.Path.mkdir
Wie 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 dasparents
Argument.Python 3.2+:
Verwenden von
pathlib
:Wenn Sie können, installieren Sie den aktuellen
pathlib
Backport mit dem Namenpathlib2
. Installieren Sie nicht den älteren nicht gepflegten Backport mit dem Namenpathlib
. 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,
pathlib
fehlt die nützlicheexist_ok
Option , obwohl es mitgeliefert wird. Der Backport soll eine neuere und überlegenere Implementierung bieten,mkdir
die diese fehlende Option enthält.Verwenden von
os
:os.makedirs
Wie oben verwendet, wird das Verzeichnis rekursiv erstellt und es wird keine Ausnahme ausgelöst, wenn das Verzeichnis bereits vorhanden ist. Es hat nur das optionaleexist_ok
Argument, wenn Python 3.2+ mit dem Standardwert von verwendet wirdFalse
. 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
pathlib
Backport mit dem Namenpathlib2
. Installieren Sie nicht den älteren nicht gepflegten Backport mit dem Namenpathlib
. Lesen Sie als Nächstes den obigen Abschnitt zu Python 3.5+ und verwenden Sie ihn auf dieselbe Weise.Verwenden von
os
:Während eine naive Lösung zuerst verwendet werden kann,
os.path.isdir
gefolgt vonos.makedirs
der 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
errno
von begrenztem Nutzen ist , weilOSError: [Errno 17] File exists
, das heißterrno.EEXIST
, erhöht wird , sowohl für Dateien und Verzeichnisse. Es ist zuverlässiger, einfach zu überprüfen, ob das Verzeichnis vorhanden ist.Alternative:
mkpath
Erstellt 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.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
mkpath
erneut verwenden, um dasselbe Verzeichnis neu zu erstellen,mkpath
werden einfach die ungültigen zwischengespeicherten Informationen verwendet, die das Verzeichnis zuvor erstellt haben, und nicht mache das Verzeichnis tatsächlich wieder. Im Gegensatz dazu istos.makedirs
kein 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.
quelle
os.path.isdir
, ob jemand anderes den Ordner löscht, der falsche, veraltete und verwirrende Fehler dieses Ordners auftritt.Die Verwendung von try Except und des richtigen Fehlercodes vom errno-Modul beseitigt die Rennbedingung und ist plattformübergreifend:
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
OSError
Erhöhung miterrno.EACCES
(Berechtigung verweigert, Fehler 13) angezeigt.quelle
exception.errno != errno.EEXIST
der 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.os.makedirs(path,exist_ok=True)
exist_ok
Parameter wurde in Python 3.2 eingeführt. Es ist in Python 2.x nicht vorhanden. Ich werde es in meine Antwort aufnehmen.Ich würde Ihnen persönlich empfehlen, statt
os.path.isdir()
zu testenos.path.exists()
.Wenn Sie haben:
Und eine dumme Benutzereingabe:
... Sie erhalten ein Verzeichnis mit dem Namen,
filename.etc
wenn Sie dieses Argument an übergeben,os.makedirs()
wenn Sie mit testenos.path.exists()
.quelle
Ü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
. (Ifexist_ok
isFalse
(Standardeinstellung)OSError
wird ausgelöst, wenn das Zielverzeichnis bereits vorhanden ist.)quelle
OSError
wird hier ausgelöst, wenn der Pfad eine vorhandene Datei oder ein vorhandenes Verzeichnis ist. Ich habe eine Antwort gepostet, um dies zu beheben.OSError
bevor Sie ihn ignorieren. Siehe stackoverflow.com/a/5032238/763269 .Ab Python 3.5
pathlib.Path.mkdir
hat eineexist_ok
Flagge:Dadurch wird das Verzeichnis rekursiv erstellt und keine Ausnahme ausgelöst, wenn das Verzeichnis bereits vorhanden ist.
(genau wie
os.makedirs
eineexist_ok
Flagge ab Python 3.2 zBos.makedirs(path, exist_ok=True)
)quelle
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:
Wir möchten vermeiden, die eingebaute Funktion zu überschreiben
dir
. Auch,filepath
oder vielleichtfullfilepath
ist wahrscheinlich ein besserer semantischer Name alsfilename
so wäre dies besser geschrieben: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 :
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.
Wenn das Verzeichnis oder die Datei nicht vorhanden ist, erhalten Sie eine
IOError
mit einer zugehörigen Fehlernummer: Zeigterrno.ENOENT
unabhängig von Ihrer Plattform auf die richtige Fehlernummer. Sie können es fangen, wenn Sie wollen, zum Beispiel: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
w
Modus öffnen (odera
anhängen) müssen. Es ist auch eine bewährte Python-Methode, den Kontextmanager zum Öffnen von Dateien zu verwenden.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
makedirs
Aufruf in einen Try-Except-Block zu packen.quelle
Probieren Sie die
os.path.exists
Funktion ausquelle
os.path.mkdir()
Methode. Das Modul os.path implementiert einige nützliche Funktionen für Pfadnamen .Ich habe folgendes niedergeschrieben. Es ist jedoch nicht absolut narrensicher.
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.
quelle
os.path.exists
- siehe stackoverflow.com/a/5032238/763269. (2) Erfolgos.path.exists
bedeutet nicht, dass das Verzeichnis vorhanden ist, sondern nur, dass der Pfad vorhanden ist existiert - kann eine Datei, ein Symlink oder ein anderes Dateisystemobjekt sein.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:
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:
Ein vielleicht noch besserer Ansatz besteht darin, das Problem der Ressourcenkonflikte zu umgehen, indem temporäre Verzeichnisse über Folgendes verwendet werden
tempfile
:Hier sind die wichtigsten Informationen aus dem Online-Dokument:
Neu in Python 3.5:
pathlib.Path
mitexist_ok
Es gibt ein neues
Path
Objekt (ab 3.4) mit vielen Methoden, die man mit Pfaden verwenden möchte - eine davon istmkdir
.(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:
Wir müssen uns jetzt nicht darum kümmern
os.path.join
- verbinden Sie einfach Pfadteile mit einem/
:Dann stelle ich idempotent sicher, dass das Verzeichnis existiert - das
exist_ok
Argument wird in Python 3.5 angezeigt:Hier ist der relevante Teil der Dokumentation :
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.
Path
Objekte müssen erzwungen werden,str
bevor andere APIs, diestr
Pfade erwarten, sie verwenden können.Vielleicht sollten Pandas aktualisiert werden, um Instanzen der abstrakten Basisklasse zu akzeptieren
os.PathLike
.quelle
In Python 3.4 können Sie auch das brandneue
pathlib
Modul verwenden :quelle
pathlib
und wopathlib2
für die neuen Benutzer zu verwenden, und ich denke, Profis hier werden die Abwertung herausfinden;)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
ist besser als die Alternative
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.
quelle
In Python3 ,
os.makedirs
Einstellung unterstütztexist_ok
. Die Standardeinstellung istFalse
, was bedeutet, dass einOSError
ausgelöst wird, wenn das Zielverzeichnis bereits vorhanden ist. Durch die Einstellungexist_ok
aufTrue
,OSError
(Verzeichnis vorhanden ist ) wird ignoriert und das Verzeichnis wird nicht erstellt werden.In Python2 wird
os.makedirs
die Einstellung nicht unterstütztexist_ok
. Sie können den Ansatz in der Antwort von heikki-toivonen verwenden :quelle
Für eine Einzeilerlösung können Sie Folgendes verwenden
IPython.utils.path.ensure_dir_exists()
: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.
quelle
IPython
ist 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 .pip install ipython
oder fügen Sie die Abhängigkeit in Ihre Anforderungen.txt oder pom.xml ein . Dokumentation: ipython.org/install.htmlSie können verwenden
mkpath
Beachten Sie, dass auch die Ahnenverzeichnisse erstellt werden.
Es funktioniert für Python 2 und 3.
quelle
distutils.dir_util
ist kein Teil der distutil public API und hat Probleme in Umgebungen mit mehreren Threads: bugs.python.org/issue10948distutils.dir_util.mkpath
darin, dass, wenn Sie ein Verzeichnis erstellen, es dann innerhalb oder außerhalb von Python löschen und dannmkpath
erneut verwenden,mkpath
einfach 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 istos.makedirs
kein solcher Cache erforderlich.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.
quelle
Sie können dafür verwenden
os.listdir
:quelle
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:
Hier sind meine Experimente / Notizen, die die Dinge klarstellen:
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
quelle
Ich sah die Antworten von Heikki Toivonen und ABB und dachte an diese Variante.
quelle
Verwenden Sie diese Befehlsprüfung und erstellen Sie ein Verzeichnis
quelle
Warum nicht das Unterprozessmodul verwenden, wenn es auf einem Computer ausgeführt wird, der Befehle
mkdir
mit-p
Option unterstützt? Funktioniert mit Python 2.7 und Python 3.6Sollte 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:
quelle
Wenn Sie Folgendes berücksichtigen:
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.
quelle
Rufen Sie die Funktion
create_dir()
am Einstiegspunkt Ihres Programms / Projekts auf.quelle
Sie müssen den vollständigen Pfad festlegen, bevor Sie das Verzeichnis erstellen:
Das funktioniert bei mir und hoffentlich auch bei Ihnen
quelle
Dadurch wird überprüft, ob die Datei vorhanden ist. Wenn dies nicht der Fall ist, wird sie erstellt.
quelle