Domanda

    

Questa domanda ha già una risposta qui:

         

Esiste un modo per ottenere funzionalità simili a mkdir -p sulla shell da Python. Sto cercando una soluzione diversa da una chiamata di sistema. Sono sicuro che il codice è inferiore a 20 righe e mi chiedo se qualcuno lo abbia già scritto?

È stato utile?

Soluzione

mkdir -p funzionalità come segue:

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

Aggiornamento

Per Python & # 8805; 3.2, os.makedirs ha un terzo argomento facoltativo exist_ok che, se vero, abilita la funzionalità mkdir -p & # 8212; a meno che viene fornito e la directory esistente ha autorizzazioni diverse da quelle previste; in tal caso, OSError viene generato come in precedenza.

Aggiornamento 2

Per Python & # 8805; 3.5, esiste anche pathlib.Path.mkdir :

import pathlib

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

Il parametro exist_ok è stato aggiunto in Python 3.5.

Altri suggerimenti

In Python > = 3.2, questo è

os.makedirs(path, exist_ok=True)

Nelle versioni precedenti, utilizzare @ tzot's answer .

Questo è più semplice che intrappolare l'eccezione:

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

Disclaimer Questo approccio richiede due chiamate di sistema che sono più suscettibili alle condizioni di gara in determinati ambienti / condizioni. Se stai scrivendo qualcosa di più sofisticato di un semplice script usa e getta in esecuzione in un ambiente controllato, è meglio andare avanti con la risposta accettata che richiede solo una chiamata di sistema.

AGGIORNAMENTO 27/07/2012

Sono tentato di eliminare questa risposta, ma penso che ci sia un valore nel thread di commento qui sotto. Come tale, lo sto convertendo in un wiki.

Di recente, ho trovato questo distutils.dir_util.mkpath :

In [17]: from distutils.dir_util import mkpath

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

mkdir -p ti dà un errore se il file esiste già:

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

Quindi un affinamento ai suggerimenti precedenti sarebbe quello di ri-codificare sollevare se os.path.isdir restituisce False (quando si seleziona per errno.EEXIST ).

(Aggiornamento) Vedi anche questo domanda molto simile ; Sono d'accordo con la risposta accettata (e avvertenze) tranne per il fatto che raccomanderei os.path.isdir invece di os.path.exists .

(Aggiorna) Per un suggerimento nei commenti, la funzione completa sarebbe simile a:

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

Come menzionato nelle altre soluzioni, vogliamo essere in grado di colpire il file system una volta mentre imita il comportamento di mkdir -p . Non penso che sia possibile farlo, ma dovremmo avvicinarci il più possibile.

Codice prima, spiegazione dopo:

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

Dato che i commenti alla risposta di @ tzot indicano che ci sono problemi nel controllare se è possibile creare una directory prima di crearla effettivamente: non si può dire se qualcuno ha cambiato il file system nel frattempo. Ciò si adatta anche allo stile di Python di chiedere perdono, non permesso.

Quindi la prima cosa che dovremmo fare è provare a creare la directory, quindi se va storto, capire perché.

Come sottolinea Jacob Gabrielson, uno dei casi che dobbiamo cercare è il caso in cui esiste già un file in cui stiamo cercando di mettere la directory.

Con mkdir -p :

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

Il comportamento analogo in Python sarebbe quello di sollevare un'eccezione.

Quindi dobbiamo capire se fosse così. Sfortunatamente, non possiamo. Riceviamo lo stesso messaggio di errore dai makedir se esiste una directory (buona) o esiste un file che impedisce la creazione della directory (cattiva).

L'unico modo per capire cosa è successo è ispezionare nuovamente il file system per vedere se c'è una directory lì. In tal caso, restituisci in silenzio, altrimenti solleva l'eccezione.

L'unico problema è che il file system potrebbe trovarsi in uno stato diverso ora rispetto a quando è stato chiamato makedirs. ad esempio: esiste un file che causa il fallimento dei makedir, ma ora una directory è al suo posto. Questo non ha molta importanza, perché la funzione si chiuderà silenziosamente senza sollevare un'eccezione quando al momento dell'ultima chiamata al file system esisteva la directory.

Con Pathlib dalla libreria standard di python3:

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

Se i genitori sono veri, tutti i genitori mancanti di questo percorso vengono creati come   necessario; vengono creati con le autorizzazioni predefinite senza accettazione   modalità in considerazione (imitando il comando POSIX mkdir -p).   Se exist_ok è falso (impostazione predefinita), viene generato un FileExistsError se   la directory di destinazione esiste già.

     

Se exist_ok è true, le eccezioni FileExistsError verranno ignorate (stesso   comportamento come comando POSIX mkdir -p), ma solo se l'ultimo percorso   componente non è un file non di directory esistente.

     

Modificato nella versione 3.5: è stato aggiunto il parametro exist_ok.

Penso che la risposta di Asa sia essenzialmente corretta, ma potresti estenderla un po 'per agire più come mkdir -p ,

import os

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

o

import os
import errno

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

Entrambi gestiscono il caso in cui il percorso esiste già in silenzio ma lasciano apparire altri errori.

Dichiarazione di funzione;

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

utilizzo:

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

Ho avuto successo con quanto segue personalmente, ma la mia funzione dovrebbe probabilmente essere chiamata come "assicurati che questa directory esista":

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
import os
import tempfile

path = tempfile.mktemp(dir=path)
os.makedirs(path)
os.rmdir(path)
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)

basato sulla risposta di @Dave C ma con un bug risolto in cui parte dell'albero esiste già

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top