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.

Ffisegydd
источник
Это хороший ответ, спасибо и отлично подходит для 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__ ,"../.."))
Себи2020
источник
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__))

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

Andyhasit
источник
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"

user11770816
источник
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

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

AlanSE
источник