Чому б використовувати обидва, os.path.abspath і os.path.realpath?


98

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

Тим НЕ менше, я вважаю , що os.path.abspath(__file__)і os.path.realpath(__file__)той же результат. os.path.abspath(os.path.realpath(__file__))здається, трохи зайвим.

Чи є причина, через яку люди цим користуються?

Відповіді:


66

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потім видаляється.


10
Хоча ця відповідь описує різницю між двома функціями, неправда, що результат realpath()може містити ..компоненти і насправді не відповідає на питання, чому ви використовуєте обидві; Відповідь Джобрада є більш точною.
Майлз

Для Python 3.7 та Windows realpath не розуміє підзаписаних дисків. Отже, для підключеного диска скажіть P: \, маючи вихідну папку c: \ MyFolder \ Bla, realpath повертає P: \ not c: \ MyFolder \ Bla. Хтось знає, як дістатися "справжнього" шляху?
Тотте Карлссон,

Для мене abspathвсе ще слідують символічні посилання, якщо поточним каталогом є символічне посилання. Я знайшов цю відповідь stackoverflow.com/questions/54665065/…, щоб зупинити цю поведінку.
Віктор Сергієнко

108

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

  • os.path.abspath повертає абсолютний шлях, але НЕ вирішує символічні посилання в аргументі.
  • os.path.realpath спочатку вирішить будь-які символічні посилання у шляху, а потім поверне абсолютний шлях.

Однак, якщо ви очікуєте, що ваш шлях міститиме ~, ні 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'

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"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.