exception liste array - Wie kann ich sicher ein verschachteltes Verzeichnis in Python erstellen?





12 Answers

Python 3.5+:

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

pathlib.Path.mkdir wie oben verwendet, erstellt das Verzeichnis rekursiv und löst keine Ausnahme aus, wenn das Verzeichnis bereits vorhanden ist. Wenn Sie nicht möchten, dass die Eltern erstellt werden, überspringen Sie das Argument der parents .

Python 3.2+:

pathlib :

Wenn möglich, installieren Sie den aktuellen pathlib Backport namens pathlib2 . Installieren Sie nicht den älteren, nicht gepflegten Rückport namens pathlib . Lesen Sie als Nächstes den Abschnitt über Python 3.5+ und verwenden Sie ihn gleich.

Wenn Sie Python 3.4 verwenden, fehlt die nützliche Option pathlib , obwohl sie mit pathlib exist_ok . Der Backport soll eine neuere und mkdir Implementierung von mkdir die diese fehlende Option beinhaltet.

Mit os :

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

os.makedirs wie oben verwendet erstellt das Verzeichnis rekursiv und löst keine Ausnahme aus, wenn das Verzeichnis bereits vorhanden ist. Es hat nur das optionale Argument exist_ok, wenn Python 3.2+ verwendet wird, mit einem Standardwert von 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+:

pathlib :

Wenn möglich, installieren Sie den aktuellen pathlib Backport namens pathlib2 . Installieren Sie nicht den älteren, nicht gepflegten Rückport namens pathlib . Lesen Sie als Nächstes den Abschnitt über Python 3.5+ und verwenden Sie ihn gleich.

Mit os :

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

Während eine naive Lösung zuerst os.path.isdir gefolgt von os.makedirs , kehrt die obige Lösung die Reihenfolge der beiden Vorgänge um. Auf diese Weise wird verhindert, dass eine häufige Racebedingung einen doppelten Versuch zur Erstellung des Verzeichnisses verursacht, und dass auch Dateien von Verzeichnissen unterschieden werden.

Beachten Sie, dass das Erfassen der Ausnahme und die Verwendung von errno von begrenztem Nutzen sind, da OSError: [Errno 17] File exists , dh errno.EEXIST wird sowohl für Dateien als auch für Verzeichnisse errno.EEXIST . Es ist zuverlässiger, einfach zu prüfen, ob das Verzeichnis existiert.

Alternative:

mkpath erstellt das verschachtelte Verzeichnis und führt nichts aus, wenn das Verzeichnis bereits vorhanden ist. Dies funktioniert in Python 2 und 3.

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

Per Bug 10948 besteht eine gravierende Einschränkung dieser Alternative darin, dass sie nur einmal pro Python-Prozess für einen bestimmten Pfad funktioniert. Wenn Sie es also zum Erstellen eines Verzeichnisses verwenden, das Verzeichnis dann innerhalb oder außerhalb von Python löschen und das Verzeichnis erneut mit mkpath erneut erstellen, verwendet mkpath die ungültigen zwischengespeicherten Informationen, indem es das Verzeichnis zuvor erstellt hat, und macht das Verzeichnis eigentlich nicht nochmal. Im Gegensatz dazu ist os.makedirs auf keinen solchen Cache angewiesen. Diese Einschränkung kann für einige Anwendungen in Ordnung sein.

Bezüglich des Modus des Verzeichnisses beziehen Sie sich bitte auf die Dokumentation, wenn Sie sich darum kümmern.

ordner wenn nicht

Was ist der eleganteste Weg, 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 ausprobiert:

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 os.path.exists vermisst (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", damit dies automatisch geschieht?




Ich würde persönlich empfehlen, dass Sie os.path.isdir() anstelle von os.path.exists() zum Testen verwenden.

>>> 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 am Ende ein Verzeichnis namens filename.etc wenn Sie dieses Argument an os.makedirs() wenn Sie mit os.path.exists() testen.




Einblicke in die Besonderheiten dieser Situation

Sie geben eine bestimmte Datei an 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. Um diesen Code zu kommentieren:

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

Wir möchten vermeiden, dass die eingebaute Funktion, dh, überschrieben wird. filepath oder fullfilepath ist wahrscheinlich ein besserer semantischer Name als filename daher wäre dies besser geschrieben:

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

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

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

Vorausgesetzt Öffnung zum Lesen

Warum sollten Sie ein Verzeichnis für eine Datei erstellen, von der Sie erwarten, dass sie dort ist und lesen 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 einen IOError mit einer zugehörigen Fehlernummer: errno.ENOENT zeigt unabhängig von Ihrer Plattform auf die richtige Fehlernummer. Sie können es fangen, wenn Sie möchten, 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

Das ist wahrscheinlich was Sie wollen.

In diesem Fall haben wir wahrscheinlich keine Rennbedingungen. Also machen Sie einfach so, wie Sie waren, aber beachten Sie, dass Sie zum Schreiben mit dem Modus w (oder a anhängenden) öffnen müssen. Es ist auch eine bewährte Methode in Python, den Kontext-Manager 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 legen. Dann kann es zu Konflikten bei der Erstellung des Verzeichnisses kommen. In diesem Fall makedirs den makedirs Aufruf am besten in einen Try- makedirs -Block.

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)



Probieren Sie die Funktion os.path.exists aus

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



Prüfen Sie, ob ein Verzeichnis existiert und erstellen Sie es ggf.?

Die direkte Antwort auf diese Frage lautet, eine einfache Situation vorauszusetzen, in der Sie nicht erwarten, dass andere Benutzer oder Prozesse Ihr Verzeichnis durcheinander bringen:

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

oder wenn das Erstellen des Verzeichnisses Race-Bedingungen unterliegt (dh wenn nach der Überprüfung des Pfads ein anderer Pfad bereits erstellt wurde), machen Sie Folgendes:

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

Ein noch besserer Ansatz ist es jedoch, das Problem mit Ressourcenkonflikten zu umgehen, indem temporäre Verzeichnisse über tempfile :

import tempfile

d = tempfile.mkdtemp()

Hier ist das Wesentliche 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.Path mit exist_ok

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

(Im Kontext verfolge ich meine wöchentliche Wiederholung mit einem Skript. Hier sind die relevanten Teile des Codes aus dem Skript, die es mir ermöglichen, zu vermeiden, dass für dieselben Daten mehr als einmal am Tag getroffen wird.)

Zuerst die relevanten Importe:

from pathlib import Path
import tempfile

Wir müssen uns jetzt nicht mit os.path.join befassen - verbinden Sie einfach os.path.join mit einem / :

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

Dann vergewissere ich mich idempotently, dass das Verzeichnis existiert - das Argument exist_ok in Python 3.5:

directory.mkdir(exist_ok=True)

Hier ist der relevante Teil der pathlib.Path.mkdir :

Wenn exist_ok true exist_ok ist, werden FileExistsError Ausnahmen ignoriert (dasselbe Verhalten wie der POSIX mkdir -p Befehl POSIX mkdir -p ), jedoch nur, wenn die letzte Pfadkomponente keine vorhandene Nichtverzeichnisdatei ist.

Hier ist ein bisschen mehr vom Skript - in meinem Fall bin ich nicht an eine Race-Bedingung gebunden. Ich habe nur einen Prozess, der erwartet, dass das Verzeichnis (oder die enthaltenen Dateien) vorhanden sind, und ich habe nichts zu entfernen versucht 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))

Pfadobjekte müssen in str erzwungen werden, bevor andere APIs, die str Pfade erwarten, sie verwenden können.

Möglicherweise sollten Pandas aktualisiert werden, um Instanzen der abstrakten Basisklasse os.PathLike zu akzeptieren.




Die entsprechende Python-Dokumentation schlägt die Verwendung des EAFP-Codierungsstils vor (Leichter als um Erlaubnis zu bitten) . 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 legt dies aufgrund der in dieser Frage behandelten Race-Bedingung nahe. Darüber hinaus gibt es, wie andere hier erwähnen, einen Leistungsvorteil, wenn das Betriebssystem einmal und nicht zweimal geprüft wird. Schließlich kann das Argument, das möglicherweise zugunsten des zweiten Codes vorgetragen wird, in einigen Fällen - wenn der Entwickler die Umgebung kennt, in der die Anwendung ausgeführt wird - nur in dem speziellen Fall befürwortet werden, für den das Programm eine private Umgebung eingerichtet hat selbst (und andere Instanzen desselben Programms).

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




In Python3 unterstützt os.makedirs die Einstellung exist_ok . Die Standardeinstellung ist False . OSError bedeutet, dass ein OSError wird, wenn das Zielverzeichnis bereits vorhanden ist. Wenn Sie exist_ok auf True , wird OSError (Verzeichnis existiert) ignoriert und das Verzeichnis wird nicht erstellt.

os.makedirs(path,exist_ok=True)

In Python2 unterstützt os.makedirs die Einstellung 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



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

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




Ich sah Heikki Toivonen und share Antworten und dachte an diese Variation.

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



Bei der Arbeit mit Datei-E / A ist Folgendes zu beachten

TOCTTOU (Zeitpunkt der Überprüfung bis zum Zeitpunkt der Verwendung)

ifWenn Sie also eine Prüfung durchführen und später lesen oder schreiben, kann dies zu einer nicht behandelten E / A-Ausnahme führen. Am besten geht es:

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



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



Verwenden Sie diesen Befehl check und erstellen Sie ein Verzeichnis

 if not os.path.isdir(test_img_dir):
     os.mkdir(str("./"+test_img_dir))



Related