python: ottieni la directory di due livelli in alto


90

Ok ... non so dove sia il modulo x, ma so che ho bisogno di ottenere il percorso della directory di due livelli superiori.

Quindi, c'è un modo più elegante per fare:

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

Le soluzioni per Python 2 e 3 sono benvenute!


1
Penso che la tua soluzione sia perfettamente a posto. Una pathlibsoluzione è un po 'più carina e più leggibile, ma non è inclusa in Python 2.7. Direi che mantieni quello che hai, magari aggiungi un commento.
jme

Forse vale la pena aggiungere l' pip install pathlib2opzione per mantenere la sanità mentale in 2.7.
jonathan

Risposte:


108

Puoi usare pathlib. Sfortunatamente questo è disponibile solo nella stdlib per Python 3.4. Se hai una versione precedente dovrai installarne una copia da PyPI qui . Questo dovrebbe essere facile da usare pip.

from pathlib import Path

p = Path(__file__).parents[1]

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

Questo utilizza la parentssequenza che fornisce l'accesso alle directory principali e sceglie la seconda in alto.

Si noti che pin questo caso sarà una qualche forma di Pathoggetto, con i propri metodi. Se hai bisogno dei percorsi come stringa, puoi chiamarli str.


Questa è una bella risposta, grazie e ottima per py3. Per py2 è possibile che non sia migliore del mio tentativo iniziale in quanto crea una dipendenza extra
jramm

16
Questa non dovrebbe essere la risposta accettata poiché quella della Pathclasse parentsdipende dalla posizione di esecuzione. Se esegui il tuo __file__dalla sua directory corrente, la Pathclasse non avrà genitori. La risposta di @ Sebi2020 dovrebbe essere accettata, oppure dovrebbe essere usato il tuo metodo originale. Credo che il tuo metodo originale sia più leggibile.
Red-Tune-84

1
Potrebbe essere necessario farlop = Path(os.path.abspath(__file__)).parents[1]
Adam Raudonis

4
@AdamRaudonis Invece di os.path.abspath, puoi anche usarePath(__file__).resolve().parents[1]
Tulio Casagrande

7
Come menzionato da @Kazanz, questa soluzione non funziona durante l'esecuzione da altri percorsi. La soluzione migliore è: p = Path(__file__).resolve().parents[1]. L'ho anche aggiunto come risposta.
Pythinker

48

Molto facile:

Ecco cosa vuoi:

import os.path as path

two_up =  path.abspath(path.join(__file__ ,"../.."))

10
E forse usa os.pardirpiuttosto che ...
jme

sys.argv [0] non restituisce il modulo che è stato eseguito da python.exe? Quindi non sarebbe necessario che funzionasse se il modulo che mi interessa fosse importato da qualche altro pacchetto .. sono proprio qui?
jramm

Se vuoi usarlo in un modulo usa invece __file__.
Sebi2020

1
@jme conosci un sistema operativo in cui ottieni la directory principale con un'altra stringa di ".." ???
Sebi2020

1
@ Sebi2020 Sì, in particolare il vecchio Mac OS. Ecco un elenco: en.wikipedia.org/wiki/Path_(computing)
jme

22

Stavo per aggiungere questo solo per essere sciocco, ma anche perché mostra ai nuovi arrivati ​​la potenziale utilità delle funzioni di aliasing e / o delle importazioni.

Dopo averlo scritto, penso che questo codice sia più leggibile (cioè meno tempo per afferrare l'intenzione) rispetto alle altre risposte fino ad oggi, e la leggibilità è (di solito) re.

from os.path import dirname as up

two_up = up(up(__file__))

Nota: vuoi fare questo genere di cose solo se il tuo modulo è molto piccolo o contestualmente coeso.


14

La migliore soluzione (per python> = 3.4) quando si esegue da qualsiasi directory è:

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

10

Per aumentare la directory di 2 livelli:

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

4

Personalmente, trovo che l'utilizzo del modulo os sia il metodo più semplice come descritto di seguito. Se stai salendo di un solo livello, sostituisci ('../ ..') con ('..').

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

--Check:
    os.getcwd()

1
È accettabile codificare come "/" mi sarei aspettato di leggere os.chdir (os.join ('..', '..'))
GreenAsJade

2

Ho scoperto che quanto segue funziona bene in 2.7.x

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

2

Puoi usarlo come soluzione generica:

import os

def getParentDir(path, level=1):
  return os.path.normpath( os.path.join(path, *([".."] * level)) )

@ JanSila: può essere più specifico, perché non è pitonico? Per leggibilità, potrebbe avere più commenti su ciò che fa, sì, ma alla fine utilizza le funzionalità del linguaggio Python standard, vedere ad esempio stackoverflow.com/questions/36901
Axel Heider

È un po 'denso, ma non credo che sia troppo astratto e non leggibile. È solo una versione generalizzata di altre risposte pubblicate qui. Tuttavia, vorrei un modo di fare le cose con una libreria standard senza la necessità di implementare una funzione.
ryanjdillon

1

Una maggiore implementazione multipiattaforma sarà:

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

L'uso parentnon è supportato su Windows. Inoltre è necessario aggiungere .resolve(), a:

Rendi il percorso assoluto, risolvendo tutti i collegamenti simbolici lungo il percorso e anche normalizzandolo (ad esempio trasformando le barre in barre rovesciate in Windows)


2
Hai una fonte per parentnon funzionare su Windows? Sembra che sia stato risolto qualche tempo da quando hai scritto questo commento. Funziona bene per me usando Python 3.7.2 su Windows 10.
Nathan

Potrei iniziare a parentlavorare su Windows 10 con Python 3.6.5. Di quale versione di python stai parlando @Zhukovgeen?
ggulgulia

@ggulgulia, credo fosse 3.7
zhukovgreen

1

Supponendo che tu voglia accedere alla cartella denominata xzy due cartelle nel tuo file python. Questo funziona per me e indipendentemente dalla piattaforma.

".././xyz"


0

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


Fornisce il percorso relativo alla directory di lavoro non al modulo
jramm

-1

Non vedo ancora una risposta valida per 2.7 che non richiede l'installazione di dipendenze aggiuntive e che parte anche dalla directory del file. Non è piacevole come soluzione a riga singola, ma non c'è niente di sbagliato nell'usare le utilità standard.

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

E per dimostrare che funziona, qui comincio ~/Documents/notessolo per mostrare che la directory corrente non influenza il risultato. Ho messo il file grandpa.pycon quello script in una cartella chiamata "scripts". Scansione fino alla directory Documents e quindi alla directory utente su un 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

Questa è l'ovvia estrapolazione della risposta per la dir genitore . Meglio usare una soluzione generale piuttosto che una soluzione meno buona in meno righe.

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.