Зачем использовать и os.path.abspath, и os.path.realpath?

99

В нескольких проектах с открытым исходным кодом я видел, как люди os.path.abspath(os.path.realpath(__file__)) получить абсолютный путь к текущему файлу.

Однако я нахожу это os.path.abspath(__file__)и получаю тот os.path.realpath(__file__)же результат.os.path.abspath(os.path.realpath(__file__))кажется немного избыточным.

Есть ли причина, по которой люди это используют?

чч
источник

Ответы:

67

os.path.realpath разграничивает символические ссылки в тех операционных системах, которые их поддерживают.

os.path.abspathпросто удаляет такие вещи, как .и ..из пути, давая полный путь от корня дерева каталогов до названного файла (или символической ссылки)

Например, в 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'

Символьные ссылки могут содержать относительные пути, поэтому необходимо использовать оба. Внутренний вызов realpathможет вернуть путь со встроенными ..частями, который abspathзатем удаляется.

kdopen
источник
10
Хотя этот ответ описывает разницу между двумя функциями, неверно, что результат realpath()может содержать ..компоненты, и на самом деле не отвечает на вопрос, почему вы должны использовать обе; Ответ Джобрада более точен.
Майлз
Для Python 3.7 и Windows realpath не понимает подключенные диски. Итак, для подключенного диска скажем P: \, имея исходную папку c: \ MyFolder \ Bla, realpath возвращает P: \, а не c: \ MyFolder \ Bla. Кто-нибудь знает, как получить «настоящий» путь?
Totte Karlsson
Для меня abspathвсе еще следовали символическим ссылкам, если текущий каталог является символической ссылкой. Я нашел этот ответ только stackoverflow.com/questions/54665065/…, чтобы остановить такое поведение.
Виктор Сергиенко
109

Для вашего заявленного сценария нет причин комбинировать realpath и abspath, поскольку os.path.realpathфактически вызывает os.path.abspathперед возвратом результата (я проверил Python 2.5 на Python 3.6).

  • os.path.abspath возвращает абсолютный путь, но НЕ разрешает символические ссылки в своем аргументе.
  • os.path.realpath сначала разрешит все символические ссылки в пути, а затем вернет абсолютный путь.

Однако, если вы ожидаете, что ваш путь будет содержать a ~, ни abspath~ , ни realpath не будут разрешены в домашний каталог пользователя, и полученный путь будет недействительным . Вам нужно будет использовать, os.path.expanduserчтобы разрешить это в каталог пользователя.

Для подробного объяснения, вот некоторые результаты, которые я проверил в Windows и Linux, в Python 3.4 и Python 2.6. Текущий каталог ( ./) - это мой домашний каталог, который выглядит так:

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
источник
3
Ницца. Чтобы подчеркнуть вашу точку зрения, ваш последний пример должен бытьos.path.realpath(os.path.expanduser('~/subdir/../data'))
Артур
3
Тогда и не стоит забывать о os.path.expandvars , если переменные используются в пути
Slavenskij
8

С точки зрения непрофессионала, если вы пытаетесь получить путь к файлу ярлыка, абсолютный путь дает полный путь к файлу, присутствующему в месте ярлыка , тогда как realpath дает путь к исходному местоположению файла.

Абсолютный путь, os.path.abspath (), дает полный путь к файлу, который находится в текущем рабочем каталоге или в указанном вами каталоге.

Реальный путь, os.path.realpath (), дает полный путь к файлу, на который делается ссылка.

Например:

file = "shortcut_folder/filename"
os.path.abspath(file) = "C:/Desktop/shortcut_folder/filename"
os.path.realpath(file) = "D:/PyCharmProjects/Python1stClass/filename"
ExtractTable.com
источник