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]))
Другие вопросы по тегам