Perché si dovrebbero usare entrambi, os.path.abspath e os.path.realpath?


98

In più progetti open source, ho visto persone fare os.path.abspath(os.path.realpath(__file__))per ottenere il percorso assoluto del file corrente.

Tuttavia, lo trovo os.path.abspath(__file__)e os.path.realpath(__file__)produco lo stesso risultato. os.path.abspath(os.path.realpath(__file__))sembra essere un po 'ridondante.

C'è un motivo per cui le persone lo usano?

Risposte:


66

os.path.realpath dereferisce i collegamenti simbolici su quei sistemi operativi che li supportano.

os.path.abspathrimuove semplicemente cose come .e ..dal percorso fornendo un percorso completo dalla radice dell'albero delle directory al file denominato (o collegamento simbolico)

Ad esempio, su Ubuntu

$ ls -l
total 0
-rw-rw-r-- 1 guest guest 0 Jun 16 08:36 a
lrwxrwxrwx 1 guest guest 1 Jun 16 08:36 b -> a

$ python
Python 2.7.11 (default, Dec 15 2015, 16:46:19) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.

>>> from os.path import abspath, realpath

>>> abspath('b')
'/home/guest/play/paths/b'

>>> realpath('b')
'/home/guest/play/paths/a'

I collegamenti simbolici possono contenere percorsi relativi, da qui la necessità di utilizzarli entrambi. La chiamata interna a realpathpotrebbe restituire un percorso con ..parti incorporate , che abspathquindi rimuove.


10
Sebbene questa risposta descriva la differenza tra le due funzioni, non è vero che il risultato di realpath()può contenere ..componenti e non risponde realmente alla domanda sul perché si dovrebbero utilizzare entrambe; la risposta di jobrad è più precisa.
Miglia

Per Python 3.7 e Windows, realpath non comprende le unità substed Quindi per un'unità substed dite P: \, avendo la cartella di origine c: \ MyFolder \ Bla, realpath restituisce P: \ non c: \ MyFolder \ Bla. Qualcuno sa come ottenere il percorso "reale"?
Totte Karlsson

Per me, abspathseguivo ancora collegamenti simbolici se la directory corrente è un collegamento simbolico. Ho trovato questa risposta solo stackoverflow.com/questions/54665065/… per interrompere questo comportamento.
Victor Sergienko

107

Per lo scenario dichiarato, non c'è motivo di combinare realpath e abspath, poiché in os.path.realpathrealtà chiama os.path.abspathprima di restituire un risultato (ho controllato da Python 2.5 a Python 3.6).

  • os.path.abspath restituisce il percorso assoluto, ma NON risolve i collegamenti simbolici nel suo argomento.
  • os.path.realpath risolverà prima tutti i collegamenti simbolici nel percorso, quindi restituirà il percorso assoluto.

Tuttavia, se ti aspetti che il tuo percorso contenga un ~, né abspath né realpath si risolveranno ~nella directory home dell'utente e il percorso risultante non sarà valido . Sarà necessario utilizzare os.path.expanduserper risolvere questo problema nella directory dell'utente.

Per una spiegazione approfondita, ecco alcuni risultati che ho verificato in Windows e Linux, in Python 3.4 e Python 2.6. La directory corrente ( ./) è la mia directory home, che assomiglia a questa:

myhome
|- data (symlink to /mnt/data)
|- subdir (extra directory, for verbose explanation)
# os.path.abspath returns the absolute path, but does NOT resolve symlinks in its argument
os.path.abspath('./')
'/home/myhome'
os.path.abspath('./subdir/../data')
'/home/myhome/data'


# os.path.realpath will resolve symlinks AND return an absolute path from a relative path
os.path.realpath('./')
'/home/myhome'
os.path.realpath('./subdir/../')
'/home/myhome'
os.path.realpath('./subdir/../data')
'/mnt/data'

# NEITHER abspath or realpath will resolve or remove ~.
os.path.abspath('~/data')
'/home/myhome/~/data'

os.path.realpath('~/data')
'/home/myhome/~/data'

# And the returned path will be invalid
os.path.exists(os.path.abspath('~/data'))
False
os.path.exists(os.path.realpath('~/data'))
False

# Use realpath + expanduser to resolve ~
os.path.realpath(os.path.expanduser('~/subdir/../data'))
'/mnt/data'

3
Bello. Per rendere il tuo punto il tuo ultimo esempio dovrebbe essereos.path.realpath(os.path.expanduser('~/subdir/../data'))
Arthur

3
Quindi non dimenticare anche os.path.expandvars se le variabili vengono utilizzate in un percorso
Slavenskij

7

In parole povere, se stai cercando di ottenere il percorso di un file di collegamento, percorso assoluto fornisce il percorso completo del file presente nella posizione del collegamento , mentre realpath fornisce il percorso della posizione originale del file.

Il percorso assoluto, os.path.abspath (), fornisce il percorso completo del file che si trova nella directory di lavoro corrente o nella directory che hai menzionato.

Il percorso reale, os.path.realpath (), fornisce il percorso completo del file a cui si fa riferimento.

Per esempio:

file = "shortcut_folder/filename"
os.path.abspath(file) = "C:/Desktop/shortcut_folder/filename"
os.path.realpath(file) = "D:/PyCharmProjects/Python1stClass/filename"
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.