2009-06-03 13 views
15

Ich brauche eine einfache Funktion, um einen Pfad in Python zu erstellen, wo die Eltern möglicherweise vorhanden sind oder nicht.Effiziente Methode zum Erstellen von rekursiven Pfaden Python

Von Python-Dokumentation wird os.makedirs fehlschlagen, wenn einer der Eltern vorhanden ist.

Ich habe die folgende Methode geschrieben, die funktioniert, macht so viele Unterverzeichnisse wie nötig.

Sieht dies effizient aus?

def create_path(path): 
    import os.path as os_path 
    paths_to_create = [] 
    while not os_path.lexists(path): 
     paths_to_create.insert(0, path) 
     head,tail = os_path.split(path) 
     if len(tail.strip())==0: # Just incase path ends with a/or \ 
      path = head 
      head,tail = os_path.split(path) 
     path = head 

    for path in paths_to_create: 
     os.mkdir(path) 

Antwort

48

"Von Python Dokumentation os.makedirs wird scheitern, wenn einer der Eltern vorhanden ist."

Nein, os.makedirs schlägt fehl, wenn das Verzeichnis selbst bereits existiert. Es wird nicht fehlschlagen, wenn nur eines der übergeordneten Verzeichnisse bereits existiert.

+0

Sind diese beiden Sätze einander widersprechen? – AlanS

+3

@AlanSha: Ja, sie widersprechen sich. Das Zitat stammt aus der Frage und enthält ein Missverständnis. Mein Kommentar versucht dann, dieses Missverständnis zu korrigieren und zu erklären, was wirklich passiert. – sth

4

Raue Entwurf:

import os 


class Path(str): 
    """ 
    A helper class that allows easy contactenation 
    of path components, creation of directory trees, 
    amongst other things. 
    """ 
    @property 
    def isdir(self): 
     return os.path.isdir(self) 

    @property 
    def isfile(self): 
     return os.path.isfile(self) 

    def exists(self): 
     exists = False 
     if self.isfile: 
      try: 
       f = open(self) 
       f.close() 
       exists = True 
      except IOError: 
       exists = False 
     else: 
      return self.isdir 
     return exists 

    def mktree(self, dirname): 
     """Create a directory tree in this directory.""" 
     newdir = self + dirname 
     if newdir.exists(): 
      return newdir 
     path = dirname.split('/') or [dirname] 
     current_path = self + path.pop(0) 
     while True: 
      try: 
       os.mkdir(current_path) 
      except OSError as e: 
       if not e.args[0] == 17: 
        raise e 
       current_path = current_path + path.pop(0) 
       continue 
      if len(path) == 0: 
       break 
     return current_path 

    def up(self): 
     """ 
     Return a new Path object set a the parent 
     directory of the current instance. 
     """ 
     return Path('/'.join(self.split('/')[:-1])) 

    def __repr__(self): 
     return "<Path: {0}>".format(self) 

    def __add__(x, y): 
     return Path(x.rstrip('/') + '/' + y.lstrip('/')) 
2

diesen Code Versuchen Sie, überprüft er, ob der Pfad bis Verzeichnisebene n Unter vorhanden ist, und das Verzeichnis erstellen, wenn nicht vorhanden ist.

def pathtodir(path): 
if not os.path.exists(path): 
    l=[] 
    p = "/" 
    l = path.split("/") 
    i = 1 
    while i < len(l): 
     p = p + l[i] + "/" 
     i = i + 1 
     if not os.path.exists(p): 
      os.mkdir(p, 0755) 
+0

Dies funktioniert nicht in Windows-Systemen –

16

Hier ist meine Take, die die Systembibliotheken alle Path-Wrangling machen können. Alle anderen Fehler als das bereits vorhandene Verzeichnis werden weitergegeben.

import os, errno 

def ensure_dir(dirname): 
    """ 
    Ensure that a named directory exists; if it does not, attempt to create it. 
    """ 
    try: 
     os.makedirs(dirname) 
    except OSError, e: 
     if e.errno != errno.EEXIST: 
      raise 
1

Ich habe diese Frage bei der Suche nach einer Möglichkeit gefunden, einfache Verzeichnisbäume innerhalb eines Projektverzeichnisses zu erstellen.

Ich bin etwas neu in Python, und ich kämpfe, wenn Datenstrukturen zu komplex, d. H. Verschachtelt werden. Es ist viel einfacher für das mentale Mapping meines Gehirns, kleine Listen von Iterablen zu verfolgen, also habe ich mir zwei sehr einfache Defs ausgedacht, die mir bei der Erstellung von Verzeichnisbäumen helfen.

Das Beispiel nimmt vier Objekte, einen Baum zu erstellen: path

  1. ein Stammverzeichnis = PROJECT_HOME
  2. ein Home-Pfad = home (erstellt, wenn es nicht, nicht überschrieben existiert) ein
  3. iterable von Verzeichnisnamen, die innerhalb von home = Zweigen eingehen (innerhalb des Home erstellt, nicht überschrieben)
  4. ein Wörterbuch mit Iterables, die auf die Zweige = Blätter abgebildet werden (jeder Wert, der in jedem zugeordneten Zweig erstellt wird, nicht überschrieben)
  5. Wenn ein Verzeichnis vorhanden ist, wird es nicht überschrieben und der Fehler wird unbemerkt übergeben.

    import os 
    from os.path import join as path_join 
    import errno 
    
    def make_node(node): 
        try: 
         os.makedirs(node) 
        except OSError, e: 
         if e.errno != errno.EEXIST: 
          raise 
    
    
    def create_tree(home, branches, leaves): 
        for branch in branches: 
         parent = path_join(home, branch) 
         make_node(parent) 
         children = leaves.get(branch, []) 
         for child in children: 
          child = os.path.join(parent, child) 
          make_node(child) 
    
    if __name__ == "__main__": 
        try: # create inside of PROJECT_HOME if it exists 
         PROJECT_HOME = os.environ['PROJECT_HOME'] 
        except KeyError: # otherwise in user's home directory 
         PROJECT_HOME = os.expanduser('~') 
    
        home = os.path.join(PROJECT_HOME, 'test_directory_tree') 
        create_tree(home, branches=[], leaves={}) 
    
        branches = (
         'docs', 
         'scripts', 
        ) 
        leaves = (
         ('rst', 'html',), 
         ('python', 'bash',) 
        ) 
        leaves = dict(list(zip(branches, leaves))) 
        create_tree(home, branches, leaves) 
    
        python_home = os.path.join(home, 'scripts', 'python') 
        branches = (
         'os', 
         'sys', 
         'text_processing', 
        ) 
        leaves = {} 
        leaves = dict(list(zip(branches, leaves))) 
        create_tree(python_home, branches, leaves) 
    
        after_thought_home = os.path.join(home, 'docs', 'after_thought') 
        branches = (
         'child_0', 
         'child_1', 
        ) 
        leaves = (
         ('sub_0', 'sub_1'), 
         (), 
        ) 
        leaves = dict(list(zip(branches, leaves))) 
        create_tree(after_thought_home, branches, leaves) 
    

Der Verzeichnisbaum, der in diesem Beispiel sieht wie folgt erstellt:

dev/test_directory_tree/ 
    ├── docs 
    │   ├── after_thought 
    │   │   ├── child_0 
    │   │   │   ├── sub_0 
    │   │   │   └── sub_1 
    │   │   └── child_1 
    │   ├── html 
    │   └── rst 
    └── scripts 
     ├── bash 
     └── python 
      ├── os 
      ├── sys 
      └── text_processing 
2

Mit Python (> = 3.4.1) gibt es exist_ok Parameter für os.makedirs.

Wenn exist_ok False ist (der Standardwert), wird ein OSError ausgelöst, wenn das Zielverzeichnis bereits existiert.

Also, wenn Sie wie exist_ok = True verwenden, wird kein Problem für die rekursive Verzeichniserstellung auftreten.

Hinweis: exist_ok kommt mit Python 3.2 auf der anderen Seite gibt es einen Bug war über das Anheben der Ausnahme, auch wenn Sie auf True gesetzt. So versucht, Python> = 3.4.1 (fest in dieser Version)

1

This code generieren Verzeichnisbaum mit bestimmten Tiefe und Breite, rekursiven Funktionsaufruf mit:

#!/usr/bin/python2.6 

import sys 
import os 

def build_dir_tree(base, depth, width): 
    print("Call #%d" % depth) 
    if depth >= 0: 
     curr_depth = depth 
     depth -= 1 
     for i in xrange(width): 
       # first creating all folder at current depth 
       os.makedirs('%s/Dir_#%d_level_%d' % (base, i, curr_depth)) 
     dirs = os.walk(base).next()[1] 
     for dir in dirs: 
       newbase = os.path.join(base,dir) 
       build_dir_tree(newbase, depth, width) 
    else: 
     return 

if not sys.argv[1:]: 
     print('No base path given') 
     sys.exit(1) 

print('path: %s, depth: %d, width: %d' % (sys.argv[1], int(sys.argv[2]), int(sys.argv[3]))) 
build_dir_tree(sys.argv[1], int(sys.argv[2]), int(sys.argv[3])) 
1

Dies ist ein alter Thread , aber ich war mit den angebotenen Lösungen nicht zufrieden, da sie für eine einfache Aufgabe meist zu kompliziert waren.

Von den verfügbaren Funktionen in der Bibliothek glaube ich, die saubersten, die wir tun können, ist:

os.path.isdir("mydir") or os.makedirs("mydir") 
Verwandte Themen