2009-06-03 92 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

「如果父母一方存在從Python文檔os.makedirs會失敗。」

不,os.makedirs將失敗,如果目錄本身已經存在。如果只有任何父目錄已經存在,它不會失敗。

+0

是這兩句話矛盾彼此? – AlanS 2012-09-25 03:20:42

+3

@AlanSha:是的,他們互相矛盾。引述來自問題幷包含誤解。我的評論然後試圖糾正這種誤解並解釋真正發生的事情。 – sth 2012-09-25 11:57:09

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

試試這個代碼,它會檢查是否存在,直到N個子目錄級別路徑,如果不存在,創建目錄。

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) 
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有些新鮮,當數據結構變得太複雜,即嵌套時,我很掙扎。我的大腦心理映射更容易追蹤小型可迭代列表,所以我想出了兩個非常基本的defs來幫助我創建目錄樹。

的例子採用四個對象來創建樹:= PROJECT_HOME

  • 歸屬路徑=家

    1. 一個根目錄路徑(創建如果它不存在,未覆蓋)
    2. 一個可迭代的將進入home = branches(在home內部創建,不會被覆蓋)的目錄名稱
    3. 映射到branches = leaves(每個映射分支內部創建的每個值,不會被覆蓋)的鍵控迭代的字典
    4. 如果存在任何目錄,則不會覆蓋它,並且錯誤會無聲無息地通過。

      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

    與Python(> = 3.4.1)存在用於os.makedirs exist_ok參數。

    如果exist_ok爲False(默認值),如果目標 目錄已存在,則會引發OSError。

    因此,如果您使用like exist_ok = True,那麼遞歸目錄創建將不會有任何問題。

    注意:exists_ok自帶python 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")