Эффективный способ создания рекурсивных путей 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)
Ответы
Ответ 1
"Из документации python os.makedirs
произойдет сбой, если один из родителей существует."
Нет, os.makedirs
завершится с ошибкой, если сама директория уже существует. Это не сработает, если уже существует какой-либо из родительских каталогов.
Ответ 2
Здесь мой take, который позволяет системным библиотекам делать все путающие споры. Все ошибки, кроме уже существующего каталога, распространяются.
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
Ответ 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
Попробуйте этот код, он проверяет, существует ли путь до 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)
Ответ 5
С python ( >= 3.4.1) существует параметр exist_ok для os.makedirs.
Если exists_ok False (по умолчанию), OSError возникает, если целевой каталог уже существует.
Итак, если вы используете like exist_ok = True, для создания рекурсивного каталога не будет никакой проблемы.
Примечание: exist_ok поставляется с python 3.2, с другой стороны, была ошибка о повышении исключения, даже если вы установите значение True. Поэтому попробуйте использовать python >= 3.4.1 (исправлено в этой версии)
Ответ 6
Я нашел этот вопрос, исследуя способ создания простых каталогов в каталоге проекта.
Я немного новичок в Python, и я борюсь, когда структуры данных становятся слишком сложными, т.е. вложенными. На моем мозговом ментальном сопоставлении намного легче отслеживать небольшие списки итераций, поэтому я придумал два основных элемента, чтобы помочь мне с созданием дерева каталогов.
В примере для создания дерева используется четыре объекта:
- корневой каталог path = PROJECT_HOME
- домашний путь = домашний (создается, если он не существует, а не перезаписывается)
- итерабельность имен каталогов, которые войдут внутрь home = branch (создаются внутри дома, а не перезаписываются)
- словарь с ключевыми итерами, которые отображаются на ветки = листья (каждое значение создается внутри каждой отображаемой ветки, а не перезаписывается).
-
Если какой-либо каталог существует, он не перезаписывается, и ошибка проходит молча.
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 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
Ответ 7
Этот код будет генерировать дерево каталогов с заданной глубиной и шириной, используя вызов рекурсивной функции:
#!/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]))
Ответ 8
Это старый поток, но я не был удовлетворен решениями, поскольку они были в основном слишком сложными для простой задачи.
Из доступных функций в библиотеке я считаю, что самое чистое, что мы можем сделать:
os.path.isdir("mydir") or os.makedirs("mydir")