¿Por qué se usarían ambos, os.path.abspath y os.path.realpath?

98

En múltiples proyectos de código abierto, he visto a personas hacer os.path.abspath(os.path.realpath(__file__))para obtener la ruta absoluta al archivo actual.

Sin embargo, lo encuentro os.path.abspath(__file__)y os.path.realpath(__file__)obtengo el mismo resultado. os.path.abspath(os.path.realpath(__file__))parece ser un poco redundante.

¿Hay alguna razón por la que la gente esté usando eso?

hch
fuente

Respuestas:

66

os.path.realpath elimina los enlaces simbólicos en los sistemas operativos que los soportan.

os.path.abspathsimplemente elimina cosas como .y ..de la ruta dando una ruta completa desde la raíz del árbol de directorios hasta el archivo nombrado (o enlace simbólico)

Por ejemplo, en 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'

Los enlaces simbólicos pueden contener rutas relativas, de ahí la necesidad de utilizar ambos. La llamada interna a realpathpodría devolver una ruta con ..partes incrustadas , que abspathluego elimina.

kdopen
fuente
10
Si bien esta respuesta describe la diferencia entre las dos funciones, no es cierto que el resultado de realpath()pueda contener ..componentes y realmente no responde a la pregunta de por qué usaría ambas; La respuesta de jobrad es más precisa.
Miles
Para Python 3.7 y Windows, realpath no comprende las unidades subtituladas. Por lo tanto, para una unidad subtitulada, diga P: \, teniendo la carpeta de origen c: \ MyFolder \ Bla, realpath devuelve P: \ no c: \ MyFolder \ Bla. ¿Alguien sabe cómo obtener el camino "real"?
Totte Karlsson
Para mí, abspathtodavía sigo enlaces simbólicos si el directorio actual es un enlace simbólico. Solo encontré esta respuesta stackoverflow.com/questions/54665065/… para detener este comportamiento.
Victor Sergienko
108

Para su escenario establecido, no hay razón para combinar realpath y abspath, ya que en os.path.realpathrealidad las llamadas os.path.abspathantes de devolver un resultado (verifiqué Python 2.5 a Python 3.6).

  • os.path.abspath devuelve la ruta absoluta, pero NO resuelve los enlaces simbólicos en su argumento.
  • os.path.realpath Primero resolverá cualquier enlace simbólico en la ruta y luego devolverá la ruta absoluta.

Sin embargo, si espera que su ruta contenga un ~, ni abspath ni realpath se resolverán ~en el directorio de inicio del usuario y la ruta resultante no será válida . Necesitará usar os.path.expanduserpara resolver esto en el directorio del usuario.

En aras de una explicación detallada, aquí hay algunos resultados que he verificado en Windows y Linux, en Python 3.4 y Python 2.6. El directorio actual ( ./) es mi directorio de inicio, que se ve así:

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
fuente
3
Agradable. Para hacer su punto, su último ejemplo debería seros.path.realpath(os.path.expanduser('~/subdir/../data'))
Arthur
3
Entonces tampoco se olvide de os.path.expandvars si se usan variables en una ruta
Slavenskij
8

En términos simples, si está tratando de obtener la ruta de un archivo de acceso directo, la ruta absoluta proporciona la ruta completa del archivo presente en la ubicación del acceso directo , mientras que realpath proporciona la ruta de ubicación original del archivo.

La ruta absoluta, os.path.abspath (), proporciona la ruta completa del archivo que se encuentra en el directorio de trabajo actual o en el directorio que mencionó.

Ruta real, os.path.realpath (), proporciona la ruta completa del archivo al que se hace referencia.

P.ej:

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