Pourquoi utiliser à la fois os.path.abspath et os.path.realpath?

98

Dans plusieurs projets open source, j'ai vu des gens faire os.path.abspath(os.path.realpath(__file__))pour obtenir le chemin absolu vers le fichier actuel.

Cependant, je trouve cela os.path.abspath(__file__)et je os.path.realpath(__file__)produit le même résultat. os.path.abspath(os.path.realpath(__file__))semble être un peu redondant.

Y a-t-il une raison pour laquelle les gens l'utilisent?

hch
la source

Réponses:

66

os.path.realpath déréfère les liens symboliques sur les systèmes d'exploitation qui les prennent en charge.

os.path.abspathsupprime simplement des choses comme .et ..du chemin en donnant un chemin complet de la racine de l'arborescence de répertoires au fichier nommé (ou lien symbolique)

Par exemple, sur 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'

Les liens symboliques peuvent contenir des chemins relatifs, d'où la nécessité d'utiliser les deux. L'appel interne à realpathpeut renvoyer un chemin avec des ..parties incorporées , qui abspathsupprime ensuite.

kdopen
la source
10
Bien que cette réponse décrit la différence entre les deux fonctions, il n'est pas vrai que le résultat de realpath()peut contenir des ..composants et ne répond pas vraiment à la question de savoir pourquoi vous utiliseriez les deux; La réponse de jobrad est plus précise.
Miles
Pour Python 3.7 et Windows, realpath ne comprend pas les lecteurs de sous-station Donc, pour un lecteur de sous-station, dites P: \, ayant le dossier source c: \ MyFolder \ Bla, realpath renvoie P: \ not c: \ MyFolder \ Bla. Quelqu'un sait comment trouver le «vrai» chemin?
Totte Karlsson
Pour moi, abspathtoujours suivi des liens symboliques si le répertoire courant est un lien symbolique. J'ai seulement trouvé cette réponse stackoverflow.com/questions/54665065/… pour arrêter ce comportement.
Victor Sergienko
108

Pour votre scénario déclaré, il n'y a aucune raison de combiner realpath et abspath, car il os.path.realpathappelle en fait os.path.abspathavant de renvoyer un résultat (j'ai vérifié Python 2.5 vers Python 3.6).

  • os.path.abspath renvoie le chemin absolu, mais ne résout PAS les liens symboliques dans son argument.
  • os.path.realpath résoudra d'abord tous les liens symboliques dans le chemin, puis retournera le chemin absolu.

Cependant, si vous prévoyez que votre chemin contient un ~, ni abspath ni realpath ne seront résolus ~dans le répertoire de base de l'utilisateur et le chemin qui en résulte sera invalide . Vous devrez utiliser os.path.expanduserpour résoudre ce problème dans le répertoire de l'utilisateur.

Pour une explication approfondie, voici quelques résultats que j'ai vérifiés sous Windows et Linux, en Python 3.4 et Python 2.6. Le répertoire courant ( ./) est mon répertoire personnel, qui ressemble à ceci:

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'
Jobrad
la source
3
Agréable. Pour faire valoir votre point, votre dernier exemple devrait êtreos.path.realpath(os.path.expanduser('~/subdir/../data'))
Arthur
3
Alors n'oubliez pas non plus os.path.expandvars si des variables sont utilisées dans un chemin
Slavenskij
8

En termes simples, si vous essayez d'obtenir le chemin d'un fichier de raccourci, le chemin absolu donne le chemin complet du fichier présent dans l' emplacement du raccourci , tandis que realpath donne le chemin de l' emplacement d'origine du fichier.

Chemin absolu, os.path.abspath (), donne le chemin complet du fichier qui se trouve dans le répertoire de travail actuel ou le répertoire que vous avez mentionné.

Le chemin réel, os.path.realpath (), donne le chemin complet du fichier référencé.

Par exemple:

file = "shortcut_folder/filename"
os.path.abspath(file) = "C:/Desktop/shortcut_folder/filename"
os.path.realpath(file) = "D:/PyCharmProjects/Python1stClass/filename"
ExtractTable.com
la source