Python: Verzeichnis zwei Ebenen höher

88

Ok ... Ich weiß nicht, wo sich das Modul xbefindet, aber ich weiß, dass ich den Pfad zum Verzeichnis zwei Ebenen höher finden muss.

Gibt es eine elegantere Möglichkeit:

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

Lösungen für Python 2 und 3 sind willkommen!

jramm
quelle
1
Ich denke, Ihre Lösung ist vollkommen in Ordnung. Eine pathlibLösung ist etwas besser und besser lesbar, ist jedoch in Python 2.7 nicht enthalten. Ich würde sagen, bleib bei dem, was du hast, füge vielleicht einen Kommentar hinzu.
jme
Vielleicht lohnt es sich, die pip install pathlib2Option zur Aufrechterhaltung der geistigen Gesundheit in 2.7 hinzuzufügen .
Jonathan

Antworten:

106

Sie können verwenden pathlib. Leider ist dies nur in der stdlib für Python 3.4 verfügbar. Wenn Sie eine ältere Version haben, müssen Sie hier eine Kopie von PyPI installieren . Dies sollte einfach zu handhaben sein pip.

from pathlib import Path

p = Path(__file__).parents[1]

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

Dies verwendet die parentsSequenz, die den Zugriff auf die übergeordneten Verzeichnisse ermöglicht, und wählt die zweite aus.

Beachten Sie, dass es sich pin diesem Fall um eine Art PathObjekt mit eigenen Methoden handelt. Wenn Sie die Pfade als Zeichenfolge benötigen, können Sie sie aufrufen str.

Ffisegydd
quelle
Das ist eine schöne Antwort, danke und großartig für py3. Für py2 ist es nicht besser als mein erster Versuch, da es eine zusätzliche Abhängigkeit schafft
jramm
16
Dies sollte nicht die akzeptierte Antwort sein, da die PathKlasse parentsvom Ausführungsort abhängt. Wenn Sie Ihre __file__aus dem aktuellen Verzeichnis ausführen, hat die PathKlasse keine Eltern. Entweder sollte die Antwort von @ Sebi2020 akzeptiert werden, oder es sollte Ihre ursprüngliche Methode verwendet werden. Ich glaube, Ihre ursprüngliche Methode ist besser lesbar.
Red-Tune-84
1
Möglicherweise müssen Sie tunp = Path(os.path.abspath(__file__)).parents[1]
Adam Raudonis
4
@AdamRaudonis Stattdessen os.path.abspathkönnen Sie auch verwendenPath(__file__).resolve().parents[1]
Tulio Casagrande
7
Wie @Kazanz erwähnt hat, funktioniert diese Lösung nicht, wenn sie von anderen Pfaden ausgeführt wird. Die beste Lösung ist : p = Path(__file__).resolve().parents[1]. Ich habe es auch als Antwort hinzugefügt.
Pythoninker
46

Sehr leicht:

Folgendes möchten Sie:

import os.path as path

two_up =  path.abspath(path.join(__file__ ,"../.."))
Sebi2020
quelle
9
Und vielleicht os.pardireher verwenden als ...
jme
Gibt sys.argv [0] kein Modul zurück, das von python.exe ausgeführt wurde? Das würde also nicht funktionieren, wenn das Modul, an dem ich interessiert bin, aus einem anderen Paket importiert worden wäre. Bin ich hier?
Diagramm
Wenn Sie es in einem Modul verwenden möchten, verwenden Sie stattdessen __file__.
Sebi2020
1
@jme Kennen Sie ein Betriebssystem, in dem Sie das übergeordnete Verzeichnis mit einer anderen Zeichenfolge als ".." erhalten?
Sebi2020
1
@ Sebi2020 Ja, insbesondere das alte Mac OS. Hier ist eine Liste: en.wikipedia.org/wiki/Path_(computing)
jme
22

Ich wollte dies nur hinzufügen, um albern zu sein, aber auch, weil es Neulingen die potenzielle Nützlichkeit von Aliasing-Funktionen und / oder Importen zeigt.

Nachdem ich es geschrieben habe, denke ich, dass dieser Code besser lesbar ist (dh weniger Zeit, um die Absicht zu erfassen) als die anderen bisherigen Antworten, und die Lesbarkeit ist (normalerweise) König.

from os.path import dirname as up

two_up = up(up(__file__))

Hinweis: Sie möchten dies nur tun, wenn Ihr Modul sehr klein oder kontextbezogen ist.

andyhasit
quelle
14

Die beste Lösung (für Python> = 3.4) bei der Ausführung aus einem beliebigen Verzeichnis ist:

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

Um das Verzeichnis 2 zu verbessern:

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

Persönlich finde ich, dass die Verwendung des OS-Moduls die einfachste Methode ist, wie unten beschrieben. Wenn Sie nur eine Ebene höher gehen, ersetzen Sie ('../ ..') durch ('..').

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

--Check:
    os.getcwd()

quelle
1
Ist es akzeptabel, das '/' fest zu codieren, von dem ich erwartet hätte, dass es os.chdir (os.join ('..', '..'))
GreenAsJade
2

Ich habe festgestellt, dass das Folgende in 2.7.x gut funktioniert

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

Sie können dies als generische Lösung verwenden:

import os

def getParentDir(path, level=1):
  return os.path.normpath( os.path.join(path, *([".."] * level)) )
Axel Heider
quelle
@ JanSila: Kann genauer sein, warum ist es nicht pythonisch? Zur besseren Lesbarkeit könnte es weitere Kommentare geben, was dies bewirkt, ja - aber am Ende werden Standardfunktionen der Python-Sprache verwendet, siehe z. B. stackoverflow.com/questions/36901
Axel Heider
Es ist ein wenig dicht, aber ich denke nicht, dass dies zu abstrakt und nicht lesbar ist. Es ist nur eine verallgemeinerte Version anderer Antworten, die hier veröffentlicht wurden. Ich möchte jedoch eine Standardbibliothek, um Dinge zu tun, ohne eine Funktion implementieren zu müssen.
Ryanjdillon
1

Weitere plattformübergreifende Implementierung wird sein:

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

Die Verwendung parentwird unter Windows nicht unterstützt. Müssen auch hinzufügen .resolve(), um:

Machen Sie den Pfad absolut, indem Sie alle Symlinks auf dem Weg auflösen und auch normalisieren (z. B. Schrägstriche unter Windows in Backslashes umwandeln).

zhukovgreen
quelle
2
Haben Sie eine Quelle dafür, dass Sie parentnicht unter Windows arbeiten? Dies scheint irgendwann behoben worden zu sein, seit Sie diesen Kommentar geschrieben haben. Es funktioniert gut für mich mit Python 3.7.2 unter Windows 10.
Nathan
Ich könnte parentan Windows 10 mit Python 3.6.5 arbeiten. Von welcher Python-Version sprichst du @Zhukovgeen?
ggulgulia
@ggulgulia Ich glaube, es war 3.7
zhukovgreen
1

Angenommen, Sie möchten auf den Ordner xzy zwei Ordner in Ihrer Python-Datei zugreifen. Dies funktioniert für mich und plattformunabhängig.

".././xyz"

user11770816
quelle
0

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

Alexis
quelle
Gibt den Pfad relativ zum Arbeitsverzeichnis und nicht zum Modul an
Diagramm
-1

Ich sehe noch keine brauchbare Antwort für 2.7, für die keine zusätzlichen Abhängigkeiten installiert werden müssen und die auch im Verzeichnis der Datei beginnt. Als einzeilige Lösung ist es nicht schön, aber es ist nichts Falsches daran, die Standarddienstprogramme zu verwenden.

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

Und um zu beweisen, dass es funktioniert, beginne ich hier ~/Documents/notesnur damit, dass das aktuelle Verzeichnis keinen Einfluss auf das Ergebnis hat. Ich habe die Datei grandpa.pymit diesem Skript in einem Ordner namens "scripts" abgelegt . Es kriecht zum Dokumentverzeichnis und dann zum Benutzerverzeichnis auf einem 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

Dies ist die offensichtliche Extrapolation der Antwort für das übergeordnete Verzeichnis . Verwenden Sie lieber eine allgemeine Lösung als eine weniger gute Lösung in weniger Zeilen.

AlanSE
quelle