Как получить местоположение родительского каталога

131

этот код получает шаблоны / blog1 / page.html в b.py:

path = os.path.join(os.path.dirname(__file__), os.path.join('templates', 'blog1/page.html'))

но я хочу получить местоположение родительского каталога:

aParent
   |--a
   |  |---b.py
   |      |---templates
   |              |--------blog1
   |                         |-------page.html
   |--templates
          |--------blog1
                     |-------page.html

и как получить местоположение aParent

Спасибо

обновлено:

это правильно:

dirname=os.path.dirname
path = os.path.join(dirname(dirname(__file__)), os.path.join('templates', 'blog1/page.html'))

или

path = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
zjm1126
источник
2
Итак, вы хотите получить blog1или a? А где находится ваш текущий файл?
Феликс Клинг,
вы понимаете, что делает ваш код?
SilentGhost
1
да, там есть шаблоны / blog1 / page.html
zjm1126
os.path.join('templates', 'blog1/page.html')мне кажется странным. Вы все путаете. Либо, os.path.join('templates', 'blog1', 'page.html')либо 'templates/blog1/page.html'. И гораздо легче будет os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))потом
Феликс Клинг
1
@zjm: нет, вы не получите эту страницу. Это не какой-то черный ящик, который вы могли бы просто использовать для получения файла шаблона. Он выполняет серию тривиальных маленьких шагов, и если бы вы могли их понять, у вас бы не возникло этого вопроса.
SilentGhost

Ответы:

173

Вы можете применить несколько раз , чтобы имя - каталога подняться выше: dirname(dirname(file)). Однако это может доходить только до корневого пакета. Если это проблема, используйте os.path.abspath: dirname(dirname(abspath(file))).

Марсело Кантос
источник
37
Я знаю, что ОП знает о dirname. Не для всех очевидно, что применение dirname к каталогу дает родительский каталог.
Марсело Кантос,
4
dirnameэто НЕ всегда возвращает родительский каталог; twitter.com/#!/ActiveState/status/671049326788608
Шридхар Ратнакумар 05
2
@Sridhar: Это зависит от вашей точки зрения; Я считаю, что путь, заканчивающийся на, /представляет собой не сам элемент конечного каталога, а его содержимое, поэтому, например, он mv xxx yyy/завершается неудачно, если yyyэто не существующий каталог. В любом случае, даже если мы примем вашу точку зрения как данность, она не имеет значения в контексте моего ответа. Ни один, fileни результат dirnameникогда не закончатся /.
Марсело Кантос
1
Незначительное исправление: dirnameможет вернуться '/', что явно заканчивается на /. Это единственное исключение, AFAIK.
Марсело Кантос
55

os.path.abspathничего не проверяет, поэтому, если мы уже добавляем строки __file__, нет необходимости беспокоиться о dirnameприсоединении или чем-либо из этого. Просто относитесь __file__к справочнику и начинайте лазить:

# climb to __file__'s parent's parent:
os.path.abspath(__file__ + "/../../")

Это гораздо менее запутанно, os.path.abspath(os.path.join(os.path.dirname(__file__),".."))и примерно так же управляемо, как dirname(dirname(__file__)). Подниматься более чем на два уровня становится нелепо.

Но, поскольку мы знаем, сколько уровней нужно подняться, мы могли бы очистить это с помощью простой небольшой функции:

uppath = lambda _path, n: os.sep.join(_path.split(os.sep)[:-n])

# __file__ = "/aParent/templates/blog1/page.html"
>>> uppath(__file__, 1)
'/aParent/templates/blog1'
>>> uppath(__file__, 2)
'/aParent/templates'
>>> uppath(__file__, 3)
'/aParent'
joemaller
источник
2
Это хорошо, но также было бы здорово, если бы стандартная библиотека добавила удобную функцию, которая выполняет это ... не хочу приходить в SO каждый раз, когда мне нужна эта
функция
4
Было os.path.abspath(os.path.join(__file__, "..", "..")бы более портативным?
slowD
40

Используйте относительный путь с pathlibмодулем в Python 3.4+:

from pathlib import Path

Path(__file__).parent

Вы можете использовать несколько вызовов, чтобы parentпродолжить путь:

Path(__file__).parent.parent

В качестве альтернативы двойному указанию parentвы можете использовать:

Path(__file__).parents[1]
Гавриэль Коэн
источник
2
Если вам нужен путь в виде строки, потому что вы хотите его изменить, вы можете просто использовать str(Path(__file__).parent).
Филипп
12
os.path.dirname(os.path.abspath(__file__))

Должен дать вам путь к a.

Но если b.pyэто файл, который в настоящее время выполняется, вы можете добиться того же, просто выполнив

os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))
Феликс Клинг
источник
1
о, я знаю, вы правы, и я хочу получить родительскую папку a. как получить
zjm1126
@ zjm1126: См. ответ Марсело Кантоса. Наносите dirname()дважды. Все, что вам сейчас нужно, должно быть на этом сайте.
Феликс Клинг,
9

os.pardirэто лучший способ ../и более читаемый.

import os
print os.path.abspath(os.path.join(given_path, os.pardir))  

Это вернет родительский путь given_path

Сунь Ливен
источник
5

Простым способом может быть:

import os
current_dir =  os.path.abspath(os.path.dirname(__file__))
parent_dir = os.path.abspath(current_dir + "/../")
print parent_dir
Муниб Али
источник
3

Может быть, объединить две ..папки, чтобы получить родительскую часть родительской папки?

path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),"..",".."))
ТЫ
источник
3

Для перехода к предыдущей папке используйте следующее:

os.chdir(os.pardir)

Если вам нужно несколько прыжков, хорошим и легким решением будет использование в этом случае простого декоратора.

Марко smdm
источник
1

Вот еще одно относительно простое решение, которое:

  • не использует dirname()(что не работает должным образом с аргументами одного уровня, такими как "file.txt" или относительными родителями, такими как "..")
  • не использует abspath() (избегая любых предположений о текущем рабочем каталоге), но вместо этого сохраняет относительный характер путей

он просто использует normpathи join:

def parent(p):
    return os.path.normpath(os.path.join(p, os.path.pardir))

# Example:
for p in ['foo', 'foo/bar/baz', 'with/trailing/slash/', 
        'dir/file.txt', '../up/', '/abs/path']:
    print parent(p)

Результат:

.
foo/bar
with/trailing
dir
..
/abs
Stefaan
источник
0

Думаю, лучше использовать это:

os.path.realpath(__file__).rsplit('/', X)[0]


In [1]: __file__ = "/aParent/templates/blog1/page.html"

In [2]: os.path.realpath(__file__).rsplit('/', 3)[0]
Out[3]: '/aParent'

In [4]: __file__ = "/aParent/templates/blog1/page.html"

In [5]: os.path.realpath(__file__).rsplit('/', 1)[0]
Out[6]: '/aParent/templates/blog1'

In [7]: os.path.realpath(__file__).rsplit('/', 2)[0]
Out[8]: '/aParent/templates'

In [9]: os.path.realpath(__file__).rsplit('/', 3)[0]
Out[10]: '/aParent'
dongweiming
источник
Не совсем, это зависит от ОС (не работает в Windows). Также он не позволяет использовать относительные пути.
kgadek
Это ужасное решение. Не будет работать для всех ОС
web.learner
0

Я попытался:

import os
os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))), os.pardir))
gogasca
источник