python: получить каталог на два уровня выше


87

Хорошо ... Я не знаю, где xнаходится модуль , но я знаю, что мне нужно получить путь к каталогу на два уровня выше.

Итак, есть ли более элегантный способ:

import os
two_up = os.path.dirname(os.path.dirname(__file__))

Решения для Python 2 и 3 приветствуются!


1
Я думаю, ваше решение совершенно нормально. pathlibРешение немного лучше и более удобным для чтения, но не входит в Python 2.7. Я бы сказал, придерживайтесь того, что у вас есть, может быть, добавьте комментарий.
— jme 08

Возможно, стоит добавить pip install pathlib2в 2.7 опцию сохранения здравомыслия.
— jonathan

Ответы:


104

Вы можете использовать pathlib. К сожалению, это доступно только в stdlib для Python 3.4. Если у вас более старая версия, вам нужно будет установить копию из PyPI здесь . Это должно быть легко сделать с помощью pip.

from pathlib import Path

p = Path(__file__).parents[1]

print(p)
# /absolute/path/to/two/levels/up

При этом используется parentsпоследовательность, которая обеспечивает доступ к родительским каталогам и выбирает второй из них.

Обратите внимание, что pв этом случае будет некая форма Pathобъекта со своими собственными методами. Если вам нужны пути в виде строки, вы можете их вызвать str.


Это хороший ответ, спасибо и отлично подходит для py3. Для py2 это возможно не лучше, чем моя первоначальная попытка, поскольку она создает дополнительную зависимость
— jramm

16
Это не должен быть принятым ответом, поскольку Pathкласс parentsзависит от места выполнения. Если вы запустите свой __file__из текущего каталога, у Pathкласса не будет родителей. Либо следует принять ответ @ Sebi2020, либо использовать ваш исходный метод. Я считаю, что ваш оригинальный метод более читабелен.
— Red-Tune-84

1
Вам может понадобиться сделатьp = Path(os.path.abspath(__file__)).parents[1]
— Адам Раудонис

4
@AdamRaudonis Вместо os.path.abspath, вы также можете использоватьPath(__file__).resolve().parents[1]
— Тулио Касагранде

7
Как упоминал @Kazanz, это решение не работает при выполнении с других путей. Лучшее решение: p = Path(__file__).resolve().parents[1]. Я тоже добавил это в качестве ответа.
— pythinker

46

Очень просто:

Вот что вам нужно:

import os.path as path

two_up =  path.abspath(path.join(__file__ ,"../.."))

8
И, возможно, os.pardirлучше использовать , чем ...
— jme 08

sys.argv [0] не возвращает модуль, запущенный python.exe? Так что это не обязательно сработает, если интересующий меня модуль был импортирован из какого-то другого пакета ... Я здесь?
— jramm 08

Если вы хотите использовать его в модуле, используйте __file__.
— Sebi2020 08

1
@jme знаете ли вы ОС, где вы получаете родительский каталог с другой строкой, кроме ".." ???
— Sebi2020 08

1
@ Sebi2020 Ага, особенно старая Mac OS. Вот список: en.wikipedia.org/wiki/Path_(computing)
— jme

22

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

Написав его, я думаю, что этот код более читабелен (то есть меньше времени для понимания намерения), чем другие ответы на сегодняшний день, и читаемость (обычно) является королем.

from os.path import dirname as up

two_up = up(up(__file__))

Примечание: вы хотите делать такие вещи только в том случае, если ваш модуль очень маленький или контекстно связный.


14

Лучшее решение (для python> = 3.4) при выполнении из любого каталога:

from pathlib import Path
two_up = Path(__file__).resolve().parents[1]

10

Чтобы поднять каталог на 2 уровня:

 import os.path as path
 two_up = path.abspath(path.join(os.getcwd(),"../.."))

4

Лично я считаю, что использование модуля os - самый простой способ, описанный ниже. Если вы поднимаетесь только на один уровень, замените ('../ ..') на ('..').

    import os
    os.chdir('../..')

--Check:
    os.getcwd()

1
Допустимо ли жестко закодировать '/', я бы ожидал прочитать os.chdir (os.join ('..', '..'))
— GreenAsJade

2

Я обнаружил, что в 2.7.x хорошо работает следующее:

import os
two_up = os.path.normpath(os.path.join(__file__,'../'))

1

Вы можете использовать это как общее решение:

import os

def getParentDir(path, level=1):
  return os.path.normpath( os.path.join(path, *([".."] * level)) )

@JanSila: можно конкретнее, почему он не питонический? Для удобства чтения в нем может быть больше комментариев о том, что это делает, да, но, в конце концов, он использует стандартные функции языка python, см., Например, stackoverflow.com/questions/36901
— Axel Heider

Это немного сложно, но я не думаю, что это слишком абстрактно и нечитабельно. Это просто обобщенная версия других ответов, размещенных здесь. Тем не менее, я хотел бы использовать стандартный библиотечный способ делать что-то без необходимости реализации функции.
— ryanjdillon

1

Более кроссплатформенная реализация будет:

import pathlib
two_up = (pathlib.Path(__file__) / ".." / "..").resolve()

Использование parentне поддерживается в Windows. Также необходимо добавить .resolve(), чтобы:

Сделайте путь абсолютным, разрешив все символические ссылки по пути, а также нормализуя его (например, превратив косую черту в обратную косую черту под Windows)


2
У вас есть причина, по которой parentне работает Windows? Кажется, это было исправлено с тех пор, как вы написали этот комментарий. У меня он отлично работает с Python 3.7.2 в Windows 10.
— Натан,

Я мог бы parentработать с Windows 10 с помощью Python 3.6.5. О какой версии python вы говорите @Zhukovgeen?
— ggulgulia

@ggulgulia, кажется, было 3,7
— zhukovgreen

0

Предполагая, что вы хотите получить доступ к папке с именем xzy, две папки в вашем файле python. Это работает для меня и не зависит от платформы.

".././xyz"


0

(pathlib.Path ('../../')) .resolve ()


Указывает путь относительно рабочего каталога, а не модуля
— jramm

-1

Я пока не вижу жизнеспособного ответа для 2.7, который не требует установки дополнительных зависимостей и также запускается из каталога файлов. Это нехорошо как однострочное решение, но в использовании стандартных утилит нет ничего плохого.

import os

grandparent_dir = os.path.abspath(  # Convert into absolute path string
    os.path.join(  # Current file's grandparent directory
        os.path.join(  # Current file's parent directory
            os.path.dirname(  # Current file's directory
                os.path.abspath(__file__)  # Current file path
            ),
            os.pardir
        ),
        os.pardir
    )
)

print grandparent_dir

И чтобы доказать, что это работает, я начинаю с ~/Documents/notesтого, чтобы показать, что текущий каталог не влияет на результат. Я положил файл grandpa.pyс этим сценарием в папку с названием "scripts". Он выполняет сканирование до каталога Documents, а затем до каталога пользователя на Mac.

(testing)AlanSE-OSX:notes AlanSE$ echo ~/Documents/scripts/grandpa.py 
/Users/alancoding/Documents/scripts/grandpa.py
(testing)AlanSE-OSX:notes AlanSE$ python2.7 ~/Documents/scripts/grandpa.py 
/Users/alancoding

Это очевидная экстраполяция ответа на родительский каталог . Лучше использовать общее решение, чем менее хорошее решение в меньшем количестве строк.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.