it-swarm.com.de

mkdir -p Funktionalität in Python

Gibt es eine Möglichkeit, Funktionen wie mkdir -p in der Shell aus Python heraus abzurufen? Ich suche eine andere Lösung als einen Systemaufruf. Ich bin sicher, dass der Code weniger als 20 Zeilen enthält, und ich frage mich, ob jemand ihn bereits geschrieben hat.

724
SetJmp

_mkdir -p_ Funktionalität wie folgt:

_import errno    
import os


def mkdir_p(path):
    try:
        os.makedirs(path)
    except OSError as exc:  # Python >2.5
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise
_

Aktualisieren

Für Python ≥ 3.2 hat _os.makedirs_ ein optionales drittes Argument _exist_ok_, das bei true die _mkdir -p_ -Funktionalität aktiviert - sofern nicht mode angegeben ist und das vorhandene Verzeichnis andere Berechtigungen als die beabsichtigten hat; In diesem Fall wird OSError wie zuvor ausgelöst.

Update 2

Für Python ≥ 3.5 gibt es auch pathlib.Path.mkdir :

_import pathlib

pathlib.Path("/tmp/path/to/desired/directory").mkdir(parents=True, exist_ok=True)
_

Der Parameter _exist_ok_ wurde in Python 3.5 hinzugefügt.

997
tzot

In Python> = 3.2 ist das

os.makedirs(path, exist_ok=True)

Verwenden Sie in früheren Versionen @ tzots Antwort .

253
Fred Foo

Dies ist einfacher als die Ausnahme abzufangen:

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

Haftungsausschluss Dieser Ansatz erfordert zwei Systemaufrufe, die unter bestimmten Umgebungen/Bedingungen anfälliger für Rennbedingungen sind. Wenn Sie etwas raffinierteres schreiben als ein einfaches Wegwerfskript, das in einer kontrollierten Umgebung ausgeführt wird, ist es besser, die akzeptierte Antwort zu wählen, für die nur ein Systemaufruf erforderlich ist.

PDATE 27.07.2012

Ich bin versucht, diese Antwort zu löschen, aber ich denke, dass der Kommentarthread unten einen Wert hat. Als solches konvertiere ich es in ein Wiki.

154
Joe Holloway

Kürzlich habe ich folgendes gefunden distutils.dir_util.mkpath :

In [17]: from distutils.dir_util import mkpath

In [18]: mkpath('./foo/bar')
Out[18]: ['foo', 'foo/bar']
47
auraham

mkdir -p gibt einen Fehler aus, wenn die Datei bereits existiert:

$ touch /tmp/foo
$ mkdir -p /tmp/foo
mkdir: cannot create directory `/tmp/foo': File exists

Eine Verfeinerung zu den vorherigen Vorschlägen wäre also, die Ausnahme erneut zu raise zu machen, wenn os.path.isdirFalse zurückgibt (wenn nach errno.EEXIST gesucht wird).

(Update) Siehe auch diese sehr ähnliche Frage ; Ich stimme der akzeptierten Antwort (und den Vorbehalten) zu, außer ich würde os.path.isdir anstelle von os.path.exists empfehlen.

(Update) Nach einem Vorschlag in den Kommentaren würde die volle Funktion so aussehen:

import os
def mkdirp(directory):
    if not os.path.isdir(directory):
        os.makedirs(directory) 
18

Mit Pathlib aus der python3-Standardbibliothek:

Path(mypath).mkdir(parents=True, exist_ok=True)

Wenn parent true ist, werden fehlende übergeordnete Elemente dieses Pfads nach Bedarf erstellt. Sie werden mit den Standardberechtigungen ohne Berücksichtigung des Modus erstellt (imitiert den POSIX-Befehl mkdir -p). Wenn exist_ok false ist (Standardeinstellung), wird ein FileExistsError ausgelöst, wenn das Zielverzeichnis bereits vorhanden ist.

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

In Version 3.5 geändert: Der exist_ok-Parameter wurde hinzugefügt.

14
Ali SAID OMAR

Wie in den anderen Lösungen erwähnt, möchten wir in der Lage sein, das Dateisystem einmal zu treffen und dabei das Verhalten von mkdir -p nachzuahmen. Ich denke nicht, dass dies möglich ist, aber wir sollten so nah wie möglich kommen.

Code zuerst, Erklärung später:

import os
import errno

def mkdir_p(path):
    """ 'mkdir -p' in Python """
    try:
        os.makedirs(path)
    except OSError as exc:  # Python >2.5
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise

Wie aus den Kommentaren zu @ tzots Antwort hervorgeht, gibt es Probleme bei der Überprüfung, ob Sie ein Verzeichnis erstellen können, bevor Sie es tatsächlich erstellen: Sie können nicht feststellen, ob das Dateisystem in der Zwischenzeit geändert wurde. Das passt auch zu Pythons Stil, um Vergebung zu bitten, nicht um Erlaubnis.

Das erste, was wir tun sollten, ist zu versuchen, das Verzeichnis zu erstellen. Wenn es schief geht, finden Sie heraus, warum.

Wie Jacob Gabrielson betont, ist einer der Fälle, nach denen wir suchen müssen, der Fall, in dem bereits eine Datei existiert, in der wir versuchen, das Verzeichnis abzulegen.

Mit mkdir -p:

$ touch /tmp/foo
$ mkdir -p /tmp/foo
mkdir: cannot create directory '/tmp/foo': File exists

Das analoge Verhalten in Python wäre, eine Ausnahme auszulösen.

Wir müssen also herausfinden, ob dies der Fall war. Leider können wir nicht. Wir erhalten die gleiche Fehlermeldung von makedirs zurück, ob ein Verzeichnis existiert (gut) oder eine Datei existiert, die die Erstellung des Verzeichnisses verhindert (schlecht).

Die einzige Möglichkeit herauszufinden, was passiert ist, besteht darin, das Dateisystem erneut zu überprüfen, um festzustellen, ob sich dort ein Verzeichnis befindet. Wenn dies der Fall ist, kehren Sie stillschweigend zurück, andernfalls lösen Sie die Ausnahme aus.

Das einzige Problem ist, dass sich das Dateisystem jetzt möglicherweise in einem anderen Status befindet als beim Aufrufen von makedirs. Beispiel: Eine Datei existierte, was dazu führte, dass Makedirs fehlschlugen, aber jetzt ist ein Verzeichnis an seiner Stelle. Das ist eigentlich nicht so wichtig, da die Funktion nur im Hintergrund beendet wird, ohne eine Ausnahme auszulösen, wenn zum Zeitpunkt des letzten Dateisystemaufrufs das Verzeichnis vorhanden war.

14
c4m3lo

Ich denke, Asas Antwort ist im Wesentlichen richtig, aber Sie könnten sie ein wenig erweitern, um sich eher wie mkdir -p zu verhalten, entweder:

import os

def mkdir_path(path):
    if not os.access(path, os.F_OK):
        os.mkdirs(path)

oder

import os
import errno

def mkdir_path(path):
    try:
        os.mkdirs(path)
    except os.error, e:
        if e.errno != errno.EEXIST:
            raise

Beide behandeln den Fall, dass der Pfad bereits unbemerkt existiert, andere Fehler jedoch auftreten.

12
davidavr

Funktionsdeklaration;

import os
def mkdir_p(filename):

    try:
        folder=os.path.dirname(filename)  
        if not os.path.exists(folder):  
            os.makedirs(folder)
        return True
    except:
        return False

verwendungszweck :

filename = "./download/80c16ee665c8/upload/backup/mysql/2014-12-22/adclient_sql_2014-12-22-13-38.sql.gz"

if (mkdir_p(filename):
    print "Created dir :%s" % (os.path.dirname(filename))
7
Guray Celik

Ich hatte persönlich Erfolg mit den folgenden Punkten, aber meine Funktion sollte wahrscheinlich so etwas wie "Sicherstellen, dass dieses Verzeichnis existiert" heißen:

def mkdirRecursive(dirpath):
    import os
    if os.path.isdir(dirpath): return

    h,t = os.path.split(dirpath) # head/tail
    if not os.path.isdir(h):
        mkdirRecursive(h)

    os.mkdir(join(h,t))
# end mkdirRecursive
4
Dave C
import os
import tempfile

path = tempfile.mktemp(dir=path)
os.makedirs(path)
os.rmdir(path)
3
pixelbeat
import os
from os.path import join as join_paths

def mk_dir_recursive(dir_path):

    if os.path.isdir(dir_path):
        return
    h, t = os.path.split(dir_path)  # head/tail
    if not os.path.isdir(h):
        mk_dir_recursive(h)

    new_path = join_paths(h, t)
    if not os.path.isdir(new_path):
        os.mkdir(new_path)

basierend auf der Antwort von @ Dave C, aber mit einem Bug, der behoben wurde, wo ein Teil des Baums bereits existiert

2
Dave00Galloway