Python идиома, чтобы получить тот же результат, что и вызов os.path.dirname несколько раз?
Я чувствую, что мне нужно получить родительский каталог файла Python в дереве исходных текстов, которое состоит из нескольких каталогов с некоторой регулярностью. Необходимость называть Dirname много раз неуклюжа.
Я огляделся и с удивлением не нашел постов по этому поводу.
Общий сценарий:
import os.path as op
third_degree_parent = op.dirname(op.dirname(op.dirname(op.realpath(__file__))))
Есть ли более идиоматический способ сделать это, не требующий вложенных вызовов dirname?
4 ответа
Нормализовать относительный путь; os.pardir
является родительским каталогом, повторяйте его столько раз, сколько необходимо. Доступно через os.path.pardir
тоже:
import os.path as op
op.abspath(op.join(__file__, op.pardir, op.pardir, op.pardir))
Кто-то еще добавил ответ в 2018 году, 4 года спустя, так почему бы не добавить мой. Другие ответы либо длинные, либо становятся длинными, если требуется большее количество родителей. Допустим, вам нужно 7 родителей. Вот что я делаю
os.path.abspath(__file__ + 8 * '/..')
Обратите внимание на дополнительные (8=7+1), чтобы удалить 7 родителей, а также имя файла. Нет необходимости os.path.pardir
как abspath
понимает /..
универсально и будет делать правильные вещи. Также имеет то преимущество, что количество родителей может быть динамическим, определяется во время выполнения.
Для сравнения эквивалент с использованием принятого ответа (более длинный и менее очевидный):
import os.path as op
op.abspath(op.join(__file__, op.pardir, op.pardir, op.pardir, op.pardir, op.pardir, op.pardir, op.pardir))
Поскольку это еще не было продемонстрировано, вот ответ с использованием рекурсивной функции.
функция
import os
def parent(path, level = 0):
parent_path = os.path.dirname(path)
if level == 0:
return parent_path
return parent(parent_path, level - 1)
Explaination
- получить имя пути, который является входным
- если уровень не равен 0, функция вызывает себя, заставляя ее получить имя dirname
- процесс повторяется до тех пор, пока уровень не достигнет 0
пример
>>> parent('/my/long/path/name/with/a/file.txt')
'/my/long/path/name/with/a'
>>> parent('/my/long/path/name/with/a/file.txt', 0)
'/my/long/path/name/with/a'
>>> parent('/my/long/path/name/with/a/file.txt', 4)
'/my/long'
def updir(d, n):
"""Given path d, go up n dirs from d and return that path"""
ret_val = d
for _ in range(n):
ret_val = os.path.dirname(ret_val)
return ret_val
Учитывая каталог d = '/path/to/some/long/dir'
Вы можете использовать вышеупомянутую функцию, чтобы пройти столько уровней, сколько хотите. Например:
updir(d,0)
'/path/to/some/long/dir'
updir(d,1)
'/path/to/some/long'
updir(d,2)
'/path/to/some'
updir(d,3)
'/path/to'
updir(d,4)
'/path'
Я расширю принятый ответ с N
import os.path as op
op.abspath(op.join(__file__, \*N\*[op.pardir]))