2009-06-03 2 views
15

Мне нужна простая функция для создания пути в Python, где родитель может или не может существовать.Эффективный способ создания рекурсивных путей Python

Из документации python os.makedirs не удастся, если один из родителей существует.

Я написал ниже метод, который работает, делая как можно больше подкаталогов.

Это выглядит эффективно?

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) 

ответ

48

«Из питона документации os.makedirs потерпит неудачу, если один из родителей не существует.»

Нет, os.makedirs не будет работать, если сама директория уже существует. Это не сработает, если уже существует какой-либо из родительских каталогов.

+0

Является ли эти два предложения противоречат друг другу? – AlanS

+3

@AlanSha: Да, они противоречат друг другу. Цитата из вопроса и содержит недоразумение. Мой комментарий затем пытается исправить это недоразумение и объяснить, что на самом деле происходит. – sth

4

черновик:

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

Попробуйте этот код, он проверяет, если путь существует до уровня каталогов п к югу, и создать каталог, если не существует.

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

Это не будет работать в системах Windows –

16

Это мой прием, который позволяет системным библиотекам делать все путы. Все ошибки, кроме уже существующего каталога, распространяются.

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

Я нашел этот вопрос, исследуя способ создания простых деревьев каталогов внутри каталога проекта.

Я несколько новичок в Python, и я борюсь, когда структуры данных становятся слишком сложными, то есть вложенными. На умственном сопоставлении моего мозга намного легче отслеживать небольшие списки итераций, поэтому я придумал два основных определения, чтобы помочь мне с созданием дерева каталогов.

Пример занимает четыре объекта для создания дерева:

путь
  1. корневой каталог = PROJECT_HOME
  2. домашний путь = дом (создан, если он не существует, не перезаписаны)
  3. итерабельными именами каталогов, которые войдут внутрь home = ветви (создаются внутри дома, а не перезаписываются)
  4. словарь с ключевыми итерами, которые отображаются на ветвях = листья (каждое значение создается внутри каждой отображаемой ветви, а не перезаписывается)
  5. Если какой-либо каталог существует, он не перезаписывается и ошибка проходит молча.

    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) 
    

дерево каталогов, что этот пример создает выглядит так:

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

С питона (> = 3.4.1) есть exist_ok параметр для os.makedirs.

Если exist_ok является False (по умолчанию), OSError возникает, если целевой каталог уже существует.

Итак, если вы используете like exist_ok = True, для создания рекурсивного каталога проблем не возникнет.

Примечание: exist_ok поставляется с питона 3.2 с другой стороны, была ошибка о повышении исключения, даже если установлено значение True. Так попробуйте использовать Python> = 3.4.1 (исправлена ​​в этой версии)

1

This code будет генерировать дерево каталогов с заданной глубины и ширины, используя рекурсивный вызов функции:

#!/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

Это старый нить , но я не был удовлетворен решениями, поскольку они были в основном слишком сложными для простой задачи.

Из доступных функций в библиотеке, я считаю, что чистейшие мы можем сделать, это:

os.path.isdir("mydir") or os.makedirs("mydir") 
Смежные вопросы