python: pobierz katalog dwa poziomy wyżej

86

Ok ... nie wiem, gdzie xjest moduł , ale wiem, że muszę uzyskać ścieżkę do katalogu dwa poziomy wyżej.

Czy jest więc bardziej elegancki sposób:

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

Mile widziane rozwiązania dla Pythona 2 i 3!

jramm
źródło
1
Myślę, że twoje rozwiązanie jest w porządku. pathlibRozwiązanie jest trochę ładniejszy i bardziej czytelne, ale nie jest wliczone w Pythonie 2.7. Powiedziałbym, że trzymaj się tego, co masz, może dodaj komentarz.
jme
Być może warto dodać pip install pathlib2opcję utrzymania rozsądku w 2.7.
Jonathan

Odpowiedzi:

104

Możesz użyć pathlib. Niestety jest to dostępne tylko w standardowej bibliotece Python 3.4. Jeśli masz starszą wersję, musisz zainstalować kopię z PyPI tutaj . Powinno to być łatwe do zrobienia za pomocą pip.

from pathlib import Path

p = Path(__file__).parents[1]

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

Używa parentssekwencji, która zapewnia dostęp do katalogów nadrzędnych i wybiera drugi w górę.

Zauważ, że pw tym przypadku będzie jakaś forma Pathobiektu z własnymi metodami. Jeśli potrzebujesz ścieżek jako łańcuchów, możesz je wywołać str.

Ffisegydd
źródło
To miła odpowiedź, dzięki i świetnie dla py3. W przypadku py2 nie jest to lepsze niż moja pierwsza próba, ponieważ tworzy dodatkową zależność
jramm
16
Nie powinna to być akceptowana odpowiedź, ponieważ Pathklasa parentszależy od miejsca wykonania. Jeśli wykonasz swój plik __file__z bieżącego katalogu, Pathklasa nie będzie miała rodziców. Albo odpowiedź @ Sebi2020 powinna zostać zaakceptowana, albo powinna zostać użyta Twoja oryginalna metoda. Uważam, że twoja oryginalna metoda jest bardziej czytelna.
Red-Tune-84
1
Być może będziesz musiał to zrobićp = Path(os.path.abspath(__file__)).parents[1]
Adam Raudonis
4
@AdamRaudonis Zamiast os.path.abspath, możesz też użyćPath(__file__).resolve().parents[1]
Tulio Casagrande.
7
Jak wspomniał @Kazanz, to rozwiązanie nie działa podczas wykonywania z innych ścieżek. Najlepszym rozwiązaniem jest: p = Path(__file__).resolve().parents[1]. Dodałem to również jako odpowiedź.
pythinker
46

Bardzo łatwe:

Oto, czego chcesz:

import os.path as path

two_up =  path.abspath(path.join(__file__ ,"../.."))
Sebi2020
źródło
8
A może os.pardirraczej użyj niż ...
jme
sys.argv [0] nie zwraca modułu uruchomionego przez python.exe? Więc nie byłaby to konieczna praca, gdyby moduł, który mnie interesował, został zaimportowany z innej paczki… jestem tutaj?
jramm
Jeśli chcesz użyć go w module, zamiast tego użyj __file__.
Sebi2020
1
@jme Czy znasz system operacyjny, w którym uzyskujesz katalog nadrzędny z innym ciągiem znaków niż „..” ???
Sebi2020,
1
@ Sebi2020 Tak, zwłaszcza stary Mac OS. Oto lista: en.wikipedia.org/wiki/Path_(computing)
jme
22

Chciałem to dodać, żeby być głupim, ale także dlatego, że pokazuje nowicjuszom potencjalną użyteczność funkcji aliasingu i / lub importu.

Po napisaniu tego uważam, że ten kod jest bardziej czytelny (tj. Krótszy czas na zrozumienie intencji) niż inne dotychczasowe odpowiedzi, a czytelność jest (zwykle) najważniejsza.

from os.path import dirname as up

two_up = up(up(__file__))

Uwaga: chcesz to zrobić tylko wtedy, gdy twój moduł jest bardzo mały lub spójny kontekstowo.

andyhasit
źródło
14

Najlepszym rozwiązaniem (dla pythona> = 3.4) podczas wykonywania z dowolnego katalogu jest:

from pathlib import Path
two_up = Path(__file__).resolve().parents[1]
pythinker
źródło
10

Aby uzyskać dostęp do katalogu 2 poziomy w górę:

 import os.path as path
 two_up = path.abspath(path.join(os.getcwd(),"../.."))
zerocog
źródło
4

Osobiście uważam, że użycie modułu os jest najłatwiejszą metodą, jak opisano poniżej. Jeśli przechodzisz tylko o jeden poziom w górę, zamień („../ ..”) na („..”).

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

--Check:
    os.getcwd()
M. Murphy
źródło
1
Czy można na stałe zakodować znak „/”, którego spodziewałbym się, że przeczytam os.chdir (os.join („..”, „..”))
GreenAsJade
2

Zauważyłem, że poniższe działa dobrze w wersji 2.7.x.

import os
two_up = os.path.normpath(os.path.join(__file__,'../'))
Lucidious
źródło
1

Możesz użyć tego jako ogólnego rozwiązania:

import os

def getParentDir(path, level=1):
  return os.path.normpath( os.path.join(path, *([".."] * level)) )
Axel Heider
źródło
@JanSila: może być bardziej szczegółowe, dlaczego nie jest pythonowe? Dla czytelności może mieć więcej komentarzy, co to robi, tak - ale ostatecznie używa standardowych funkcji języka Python, patrz np. Stackoverflow.com/questions/36901
Axel Heider
Jest trochę gęsty, ale nie sądzę, żeby był zbyt abstrakcyjny i nieczytelny. To tylko uogólniona wersja innych odpowiedzi zamieszczonych tutaj. Chciałbym jednak robić rzeczy w standardowej bibliotece bez potrzeby implementowania funkcji.
ryanjdillon
1

Bardziej wieloplatformowe wdrożenie będzie:

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

Używanie parentnie jest obsługiwane w systemie Windows. Należy również dodać .resolve()do:

Uczyń ścieżkę absolutną, rozwiązując wszystkie linki symboliczne po drodze, a także normalizując ją (na przykład zamieniając ukośniki na ukośniki odwrotne w systemie Windows)

zhukovgreen
źródło
2
Czy masz źródło, które parentnie działa w systemie Windows? Wydaje się, że zostało to naprawione jakiś czas temu, odkąd napisałeś ten komentarz. U mnie działa dobrze, używając Pythona 3.7.2 w systemie Windows 10.
Nathan,
mógłbym zacząć parentpracować na systemie Windows 10 z Pythonem 3.6.5. O której wersji Pythona mówisz @Zhukovgeen?
ggulgulia
@ggulgulia Myślę, że to było 3,7
zhukovgreen
0

Zakładając, że chcesz uzyskać dostęp do folderu o nazwie xzy dwa foldery w pliku Pythona. To działa dla mnie i niezależnie od platformy.

„.././xyz”

user11770816
źródło
0

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

Alexis
źródło
Podaje ścieżkę względem katalogu roboczego, a nie modułu
jramm
-1

Nie widzę jeszcze realnej odpowiedzi na 2.7, która nie wymaga instalowania dodatkowych zależności, a także zaczyna się od katalogu pliku. Nie jest to przyjemne rozwiązanie jednokreskowe, ale nie ma nic złego w korzystaniu ze standardowych narzędzi.

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

Aby udowodnić, że to działa, zacznę tutaj, ~/Documents/notesaby pokazać, że bieżący katalog nie wpływa na wynik. Umieściłem plik grandpa.pyz tym skryptem w folderze o nazwie „scripts”. Przeszukuje do katalogu Dokumenty, a następnie do katalogu użytkownika na komputerze 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

To oczywista ekstrapolacja odpowiedzi dla rodzica reż . Lepiej jest użyć rozwiązania ogólnego niż mniej dobrego w mniejszej liczbie wierszy.

AlanSE
źródło
-1

dla py 3.4 i nowszych, pathlib

przykład:

from pathlib import Path
path = Path("../../data/foo/someting.csv").resolve()
O-9
źródło
Daje to ścieżkę względem katalogu roboczego, a nie modułu
jramm