Як отримати місце розташування батьків


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__),".."))

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
Шрідхар Ратнакумар

2
@Sridhar: Це залежить від вашої точки зору; Я вважаю, що шлях, що закінчується /, не представляє собою саму запис каталогу каталогів, а її вміст, і саме тому, наприклад, mv xxx yyy/виходить з ладу, якщо yyyце не існуючий каталог. У будь-якому випадку, навіть якщо ми сприймаємо вашу думку як дану, це не має значення в контексті моєї відповіді. Ні, fileні результат dirnameволі ніколи не закінчиться /.
Марсело Кантос

1
Незначна корекція: dirnameможе повернутися '/', що явно закінчується a /. Це єдиний виняток, AFAIK.
Marcelo Cantos

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'

2
Це добре, але було б також здорово, якби стандартна бібліотека додала функцію зручності, яка це здійснила ... не хочу приїжджати до
ТА

4
Були os.path.abspath(os.path.join(__file__, "..", "..")б більш портативними?
повільноD

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
o, я знаю, ти маєш рацію, і я хочу отримати батьківську папку. як його отримати
zjm1126

@ zjm1126: Дивіться відповідь Марсело Кантоса. Наносити dirname()двічі. Все, що вам потрібно зараз, має бути на цьому сайті.
Фелікс Клінг

9

os.pardirє кращим способом ../і читабельнішим.

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

Це поверне батьківський шлях заданого_пуття


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)

Якщо вам потрібні кілька стрибків, хорошим і легким рішенням буде використовувати простий декоратор в цьому випадку.


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

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'

Не зовсім, це залежить від ОС (не буде працювати в 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))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.