Come ottenere la posizione della directory principale


131

questo codice è ottenere i template / blog1 / page.html in b.py:

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

ma voglio ottenere la posizione della directory principale padre:

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

e come ottenere la posizione aParent

Grazie

aggiornamento:

è giusto:

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

o

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

2
Quindi vuoi ottenere blog1o a? E dove si trova il tuo file attuale?
— Felix Kling,

capisci cosa sta facendo il tuo codice?
— SilentGhost,

1
sì, ottiene i template / blog1 / page.html
— zjm1126

os.path.join('templates', 'blog1/page.html')mi sembra strano. Stai mescolando le cose. O os.path.join('templates', 'blog1', 'page.html')oppure 'templates/blog1/page.html'. E molto più facile sarebbe os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))allora
— Felix Kling,

1
@zjm: no, non ottieni quella pagina. Non è una blackbox che potresti semplicemente usare per ottenere il file modello. Esegue una serie di piccoli passi insignificanti e se tu potessi capirli, non avresti questa domanda.
— SilentGhost,

Risposte:


173

È possibile applicare nomedir ripetutamente per salire più in alto: dirname(dirname(file)). Questo può arrivare solo fino al pacchetto root, comunque. Se questo è un problema, utilizzare os.path.abspath: dirname(dirname(abspath(file))).


37
So che l'OP lo sa dirname. Non è ovvio per tutti che l'applicazione di dirname a una directory produce la directory principale.
— Marcelo Cantos,

4
dirnamenon non tornare sempre nella directory superiore; twitter.com/#!/ActiveState/status/671049326788608
— Sridhar Ratnakumar

2
@Sridhar: dipende dalla tua prospettiva; Considero un percorso che termina /come non rappresenta la voce della directory foglia stessa, ma il suo contenuto, motivo per cui, ad esempio, mv xxx yyy/fallisce se yyynon è una directory preesistente. In ogni caso, anche se consideriamo il tuo punto come dato, è irrilevante nel contesto della mia risposta. Né fileil risultato di dirnameWill finirà mai in a /.
— Marcelo Cantos,

1
Correzione minore: dirnamepuò tornare '/', che termina chiaramente in a /. Questa è l'unica eccezione, AFAIK.
— Marcelo Cantos,

55

os.path.abspathnon convalida nulla, quindi se stiamo già aggiungendo stringhe a __file__non è necessario preoccuparsi dirnameo unirsi o altro. Tratta __file__come una directory e inizia a scalare:

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

È molto meno contorto di os.path.abspath(os.path.join(os.path.dirname(__file__),".."))quanto sia gestibile dirname(dirname(__file__)). L'arrampicata su più di due livelli inizia a diventare ridicola.

Ma, poiché sappiamo quanti livelli salire, potremmo ripulirlo con una semplice piccola funzione:

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'

2
Questo è bello, ma sarebbe anche bello se la libreria standard aggiungesse una funzione di convenienza che lo ha fatto ... non voglio venire su SO ogni volta che ho bisogno di questa funzione
— gradi3nt

4
Sarebbe os.path.abspath(os.path.join(__file__, "..", "..")più portatile?
— slowD

40

Usa il percorso relativo conpathlib modulo in Python 3.4+:

from pathlib import Path

Path(__file__).parent

È possibile utilizzare più chiamate a parent per andare oltre nel percorso:

Path(__file__).parent.parent

In alternativa alla specifica parentdue volte, è possibile utilizzare:

Path(__file__).parents[1]

2
Se hai bisogno del percorso come stringa perché vuoi modificarlo, puoi semplicemente usare str(Path(__file__).parent).
— Philipp

12
os.path.dirname(os.path.abspath(__file__))

Dovrebbe darti il ​​percorso per a.

Ma se b.pyè il file che è attualmente in esecuzione, allora puoi ottenere lo stesso semplicemente facendo

os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))

1
o, lo so, hai ragione, e voglio ottenere la cartella principale di a. come ottenerlo
— zjm1126,

@ zjm1126: vedi la risposta di Marcelo Cantos. Applicare dirname()due volte. Tutto ciò di cui hai bisogno ora dovrebbe essere su questo sito.
— Felix Kling

9

os.pardirè un modo migliore per ../e più leggibile.

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

Ciò restituirà il percorso principale del dato percorso


5

Un modo semplice può essere:

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

3

Può essere unire due ..cartelle, per ottenere padre della cartella padre?

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

3

Utilizzare quanto segue per passare alla cartella precedente:

os.chdir(os.pardir)

Se hai bisogno di più salti, in questo caso una soluzione semplice e buona sarà usare un semplice decoratore.


1

Ecco un'altra soluzione relativamente semplice che:

  • non utilizza dirname()(che non funziona come previsto su argomenti di un livello come "file.txt" o relativi genitori come "..")
  • non utilizza abspath()(evitando ipotesi sulla directory di lavoro corrente) ma conserva invece il carattere relativo dei percorsi

utilizza normpathe 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)

Risultato:

.
foo/bar
with/trailing
dir
..
/abs

0

Penso che usare questo sia meglio:

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'

Non del tutto, dipende dal sistema operativo (non funzionerà su Windows). Inoltre, non consente di utilizzare percorsi relativi.
— kgadek,

Questa è una soluzione terribile. Non funzionerà con tutti i SO
— web.learner,

0

Provai:

import os
os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))), os.pardir))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.