2010-05-12 11 views
94

questo codice è ottenere il templates/blog1/page.html in b.py:Come ottenere la posizione genitore dir

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

ma voglio ottenere la posizione genitore dir:

e come ottenere la posizione aparent

grazie

aggiornamento:

questo è 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 'blog1' o' a'? E dove si trova il tuo file corrente? –

+0

capisci cosa sta facendo il tuo codice? – SilentGhost

+1

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

risposta

114

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

+1

sembra sapere di 'dirname' – SilentGhost

+29

So che l'OP sa di' dirname'. Non è ovvio per tutti che applicare dirname a una directory produca la directory genitore. –

+0

ciao Marcelo, guarda l'aggiornato – zjm1126

3

È possibile unire due cartelle .. per ottenere il padre della cartella principale?

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

dovrebbe darvi il percorso di a.

Ma se b.py è il file che viene attualmente eseguito, allora si può ottenere lo stesso da solo facendo

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

o, lo so, hai ragione, e voglio ottenere la cartella genitore di a. come ottenerlo – zjm1126

+0

@ zjm1126: vedi la risposta di Marcelo Cantos. Applica 'dirname()' due volte. Tutto ciò di cui hai bisogno ora dovrebbe essere su questo sito. –

37

os.path.abspath non convalida nulla, quindi se stiamo già aggiungendo stringhe per __file__ non c'è bisogno di dare fastidio con dirname o partecipare a uno di questi. Proprio trattare __file__ come una directory e iniziare a salire:

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

Questo è molto meno complicata di quanto os.path.abspath(os.path.join(os.path.dirname(__file__),"..")) e quanto di più gestibile come dirname(dirname(__file__)). Arrampicare più di due livelli inizia a diventare ridicolo.

Ma, poiché sappiamo quanti livelli a salire, si potrebbe pulire questo 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' 
+0

Mi piace questa risposta migliore^ – Stephen

+0

Eccellente approccio – MA1

+2

Questo è bello, ma sarebbe anche bello se la libreria standard aggiungesse una funzione di convenienza che ha portato a termine questo ... non voglio venire in SO ogni volta che ho bisogno di questa funzione – gradi3nt

2

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 
7

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

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

Ciò restituirà il percorso principale della given_path

0

Penso uso questo è 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' 
+0

Non proprio, dipende dal SO (non funzionerà su Windows). Inoltre non consente di utilizzare percorsi relativi. – kgadek

0

Ecco un'altra soluzione relativamente semplice che:

  • non lo fa utilizzare dirname() (che non funziona come previsto su argomenti di livello come "file.txt" o relativi genitori come "..")
  • non usa abspath() (evitando qualsiasi ipotesi circa la directory di lavoro corrente), ma invece conserva il carattere relativo di percorsi

usa solo normpath e 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

Ho provato:

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

Usare il seguente per passare alla cartella precedente:

os.chdir(os.pardir) 

Se avete bisogno di salti multipli una soluzione buona e facile sarà quello di utilizzare un semplice decoratore in questo caso.

12

È possibile utilizzare il modulo pathlib in Python 3.4+:

from pathlib import Path 

Path(__file__).parent 

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

Path(__file__).parent.parent 

Come alternativa a specificare parent due volte , puoi usare

Path(__file__).parents[1] 
Problemi correlati