python: отримати каталог на два рівні вище


87

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

Отже, чи є більш елегантний спосіб зробити:

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

Рішення для Python 2 і 3 вітаються!


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

Можливо, варто додати pip install pathlib2опцію збереження здорового глузду в 2.7.
Джонатан

Відповіді:


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]
Tulio Casagrande

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

sys.argv [0] не повертає модуль, запущений python.exe? Отже, це не повинно працювати, якщо модуль, який мене цікавить, був імпортований з іншого пакета ..
jramm

Якщо ви хочете використовувати його в модулі, натомість використовуйте __file__.
Sebi2020

1
@jme ти знаєш ОС, де ти отримуєш батьківський каталог із іншим рядком, ніж ".." ???
Sebi2020

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]


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
Аксель Хайдер

Це трохи щільно, але я не думаю, що це занадто абстрактно і не читається. Це лише узагальнена версія інших відповідей, розміщених тут. Я хотів би стандартний спосіб роботи в бібліотеці без необхідності реалізації функції.
рянджділлон,

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
жуковгрін

0

Припускаючи, що ви хочете отримати доступ до папки з назвою xzy, дві папки до вашого файлу python. Це працює для мене і не залежить від платформи.

".././xyz"



-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із цим сценарієм у папку "сценарії". Він переповзає до папки "Документи", а потім до папки користувача на 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.