So erhalten Sie den Speicherort des übergeordneten Verzeichnisses

129

Dieser Code enthält die Vorlagen / blog1 / page.html in b.py:

path = os.path.join(os.path.dirname(__file__), os.path.join('templates', 'blog1/page.html'))

aber ich möchte den übergeordneten Verzeichnisspeicherort erhalten:

aParent
   |--a
   |  |---b.py
   |      |---templates
   |              |--------blog1
   |                         |-------page.html
   |--templates
          |--------blog1
                     |-------page.html

und wie man den aParent-Standort erhält

Vielen Dank

Aktualisiert:

Dies ist richtig:

dirname=os.path.dirname
path = os.path.join(dirname(dirname(__file__)), os.path.join('templates', 'blog1/page.html'))

oder

path = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
zjm1126
quelle
2
Also willst du bekommen blog1oder a? Und wo befindet sich Ihre aktuelle Datei?
Felix Kling
Verstehst du, was dein Code tut?
SilentGhost
1
Ja, es bekommt die Vorlagen / blog1 / page.html
zjm1126
os.path.join('templates', 'blog1/page.html')sieht für mich seltsam aus. Sie vermischen die Dinge. Entweder os.path.join('templates', 'blog1', 'page.html')oder 'templates/blog1/page.html'. Und viel einfacher wäre os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))dann
Felix Kling
1
@zjm: Nein, du bekommst diese Seite nicht. Es ist keine Blackbox, mit der Sie nur die Vorlagendatei abrufen können. Es führt eine Reihe trivialer kleiner Schritte aus, und wenn Sie sie verstehen könnten, hätten Sie diese Frage nicht.
SilentGhost

Antworten:

170

Sie können dirname wiederholt anwenden, um höher zu klettern : dirname(dirname(file)). Dies kann jedoch nur bis zum Root-Paket gehen. Wenn dies ein Problem ist, verwenden Sie os.path.abspath: dirname(dirname(abspath(file))).

Marcelo Cantos
quelle
37
Ich weiß, dass das OP davon weiß dirname. Es ist nicht für alle offensichtlich, dass das Anwenden von dirname auf ein Verzeichnis das übergeordnete Verzeichnis ergibt.
Marcelo Cantos
4
dirnamegibt NICHT immer das übergeordnete Verzeichnis zurück; twitter.com/#!/ActiveState/status/671049326788608
Sridhar Ratnakumar
2
@Sridhar: Das hängt von deiner Perspektive ab. Ich betrachte einen Pfad, der mit endet, /als nicht den Blattverzeichniseintrag selbst darstellend, sondern dessen Inhalt, weshalb z. B. mv xxx yyy/fehlschlägt, wenn yyyes sich nicht um ein bereits vorhandenes Verzeichnis handelt. In jedem Fall ist es im Kontext meiner Antwort irrelevant, auch wenn wir Ihren Standpunkt als gegeben betrachten. Weder filenoch das Ergebnis von dirnamewird jemals in a enden /.
Marcelo Cantos
1
Kleinere Korrektur: dirnameKann zurückkehren '/', was eindeutig in a endet /. Das ist die einzige Ausnahme, AFAIK.
Marcelo Cantos
55

os.path.abspathvalidiert nichts. Wenn wir also bereits Zeichenfolgen anhängen, müssen Sie __file__sich nicht darum kümmern dirnameoder beitreten oder irgendetwas davon. Behandle es einfach __file__als Verzeichnis und beginne zu klettern:

# climb to __file__'s parent's parent:
os.path.abspath(__file__ + "/../../")

Das ist weit weniger kompliziert als os.path.abspath(os.path.join(os.path.dirname(__file__),".."))und ungefähr so ​​überschaubar wie dirname(dirname(__file__)). Das Klettern in mehr als zwei Levels wird langsam lächerlich.

Da wir jedoch wissen, wie viele Ebenen zu erklimmen sind, können wir dies mit einer einfachen kleinen Funktion bereinigen:

uppath = lambda _path, n: os.sep.join(_path.split(os.sep)[:-n])

# __file__ = "/aParent/templates/blog1/page.html"
>>> uppath(__file__, 1)
'/aParent/templates/blog1'
>>> uppath(__file__, 2)
'/aParent/templates'
>>> uppath(__file__, 3)
'/aParent'
Joemaller
quelle
2
Das ist schön, aber es wäre auch cool, wenn die Standardbibliothek eine Komfortfunktion hinzufügen würde, die dies erreicht ... Ich möchte nicht jedes Mal zu SO kommen, wenn ich diese Funktion benötige
Gradi3nt
4
Wäre os.path.abspath(os.path.join(__file__, "..", "..")tragbarer?
SlowD
40

Verwenden Sie den relativen Pfad mit dem pathlibModul in Python 3.4+:

from pathlib import Path

Path(__file__).parent

Sie können mehrere Aufrufe verwenden parent, um den Pfad weiter zu verfolgen:

Path(__file__).parent.parent

Alternativ zur parentzweimaligen Angabe können Sie Folgendes verwenden:

Path(__file__).parents[1]
Gavriel Cohen
quelle
2
Wenn Sie den Pfad als Zeichenfolge benötigen, weil Sie ihn ändern möchten, können Sie ihn einfach verwenden str(Path(__file__).parent).
Philipp
12
os.path.dirname(os.path.abspath(__file__))

Sollte dir den Weg geben a.

Wenn b.pyes sich jedoch um die Datei handelt, die gerade ausgeführt wird, können Sie dasselbe erreichen, indem Sie dies einfach tun

os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))
Felix Kling
quelle
1
o, ich weiß, du hast recht und ich möchte den übergeordneten Ordner des a bekommen. wie man es bekommt
zjm1126
@ zjm1126: Siehe Marcelo Cantos 'Antwort. dirname()Zweimal auftragen . Alles, was Sie jetzt brauchen, sollte auf dieser Seite sein.
Felix Kling
9

os.pardirist ein besserer Weg ../und besser lesbar.

import os
print os.path.abspath(os.path.join(given_path, os.pardir))  

Dies gibt den übergeordneten Pfad des angegebenen Pfads zurück

Sun Liwen
quelle
5

Ein einfacher Weg kann sein:

import os
current_dir =  os.path.abspath(os.path.dirname(__file__))
parent_dir = os.path.abspath(current_dir + "/../")
print parent_dir
Muneeb Ali
quelle
3

Kann zwei ..Ordner verbinden, um Eltern des übergeordneten Ordners zu bekommen?

path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),"..",".."))
SIE
quelle
3

Verwenden Sie Folgendes, um zum vorherigen Ordner zu springen:

os.chdir(os.pardir)

Wenn Sie mehrere Sprünge benötigen, ist es in diesem Fall eine gute und einfache Lösung, einen einfachen Dekorateur zu verwenden.

Marco smdm
quelle
1

Hier ist eine andere relativ einfache Lösung, die:

  • wird nicht verwendet dirname()(was bei einstufigen Argumenten wie "file.txt" oder relativen Eltern wie ".." nicht wie erwartet funktioniert)
  • wird nicht verwendet abspath()(wobei Annahmen über das aktuelle Arbeitsverzeichnis vermieden werden), sondern behält den relativen Charakter von Pfaden bei

es verwendet nur normpathund join:

def parent(p):
    return os.path.normpath(os.path.join(p, os.path.pardir))

# Example:
for p in ['foo', 'foo/bar/baz', 'with/trailing/slash/', 
        'dir/file.txt', '../up/', '/abs/path']:
    print parent(p)

Ergebnis:

.
foo/bar
with/trailing
dir
..
/abs
Stefaan
quelle
0

Ich denke, dies zu verwenden ist besser:

os.path.realpath(__file__).rsplit('/', X)[0]


In [1]: __file__ = "/aParent/templates/blog1/page.html"

In [2]: os.path.realpath(__file__).rsplit('/', 3)[0]
Out[3]: '/aParent'

In [4]: __file__ = "/aParent/templates/blog1/page.html"

In [5]: os.path.realpath(__file__).rsplit('/', 1)[0]
Out[6]: '/aParent/templates/blog1'

In [7]: os.path.realpath(__file__).rsplit('/', 2)[0]
Out[8]: '/aParent/templates'

In [9]: os.path.realpath(__file__).rsplit('/', 3)[0]
Out[10]: '/aParent'
Dongweiming
quelle
Nicht ganz, es ist vom Betriebssystem abhängig (funktioniert unter Windows nicht). Es ist auch nicht erlaubt, relative Pfade zu verwenden.
kgadek
Das ist eine schreckliche Lösung.
Funktioniert
0

Ich habe es versucht:

import os
os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))), os.pardir))
Gogasca
quelle