创建递归路径Python的有效方法

Posted

技术标签:

【中文标题】创建递归路径Python的有效方法【英文标题】:Efficient way of creating recursive paths Python 【发布时间】:2010-10-30 23:32:21 【问题描述】:

我需要一个简单的函数来在 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)

【问题讨论】:

【参考方案1】:

“来自 python 文档 os.makedirs 将失败,如果其中一个父母存在。”

不,如果目录本身已经存在,os.makedirs 将失败。如果仅存在任何父目录,它不会失败。

【讨论】:

这两句话有矛盾吗? @AlanSha:是的,它们相互矛盾。引用来自问题并包含误解。然后我的评论试图纠正这种误解并解释真正发生的事情。【参考方案2】:

这是我的看法,它让系统库完成所有路径争论。除了已经存在的目录之外的任何错误都会传播。

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

【讨论】:

请注意,在 Python 3 中,ok.makedirs 也接受 exists_ok,您可以将其设置为 True 并避免实现此包装器。另见***.com/a/29508062/1467943【参考方案3】:

草稿:

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('/'))

【讨论】:

【参考方案4】:

对于 python ( >=3.4.1 ),os.makedirs 有 exists_ok 参数。

如果 exists_ok 为 False(默认值),如果目标 目录已存在。

所以如果你使用 like exists_ok=True ,递归目录创建不会有任何问题。

注意:exist_ok 是 python 3.2 自带的,但存在一个 bug 即使您设置为 True,也会引发异常。所以尝试使用 python >= 3.4.1(该版本已修复)

【讨论】:

【参考方案5】:

试试这个代码,它检查路径是否存在直到 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)

【讨论】:

【参考方案6】:

这是一个旧线程,但我对所提供的解决方案并不满意,因为它们对于简单的任务来说大多过于复杂。

从库中的可用函数中,我相信我们能做的最干净的是:

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

【讨论】:

【参考方案7】:

我在研究一种在项目目录中制作简单目录树的方法时发现了这个问题。

我对 Python 有点陌生,当数据结构变得过于复杂(即嵌套)时,我会遇到困难。在我的大脑的思维导图中,跟踪小型迭代列表要容易得多,所以我想出了两个非常基本的定义来帮助我创建目录树。

该示例使用四个对象来创建一棵树:

    根目录路径 = PROJECT_HOME 主路径 = 主路径(如果不存在则创建,不会被覆盖) 将进入 home = 分支的目录名称的可迭代(在 home 内部创建,不会被覆盖) 映射到分支 = 叶子的键控迭代字典(在每个映射分支内部创建的每个值,不会被覆盖)

    如果任何目录存在,它不会被覆盖,错误会静默传递。

    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

【讨论】:

【参考方案8】:

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

【讨论】:

以上是关于创建递归路径Python的有效方法的主要内容,如果未能解决你的问题,请参考以下文章

Python 常用基础模块:os模块

Python mkdir & makedirs

使用 python 子进程创建计划任务

PHP中常用操作文件的方法

Java基础-File类篇递归篇

如何使用 Python 创建文件路径的 zip 文件,包括空目录?