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.