Po co używać obu, os.path.abspath i os.path.realpath?

99

W wielu projektach typu open source widziałem, jak ludzie próbują os.path.abspath(os.path.realpath(__file__))uzyskać bezwzględną ścieżkę do bieżącego pliku.

Jednak znajduję to os.path.abspath(__file__)i daję os.path.realpath(__file__)ten sam wynik. os.path.abspath(os.path.realpath(__file__))wydaje się być trochę zbędny.

Czy jest jakiś powód, dla którego ludzie tego używają?

hch
źródło

Odpowiedzi:

67

os.path.realpath wyodrębnia dowiązania symboliczne w tych systemach operacyjnych, które je obsługują.

os.path.abspathpo prostu usuwa takie rzeczy jak .i ..ze ścieżki, dając pełną ścieżkę od katalogu głównego do nazwanego pliku (lub dowiązania symbolicznego)

Na przykład w systemie 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'

Dowiązania symboliczne mogą zawierać ścieżki względne, stąd potrzeba użycia obu. Wewnętrzne wywołanie realpathmoże zwrócić ścieżkę z osadzonymi ..częściami, która abspathnastępnie zostanie usunięta.

kdopen
źródło
10
Chociaż ta odpowiedź opisuje różnicę między tymi dwiema funkcjami, nie jest prawdą, że wynik realpath()może zawierać ..komponenty i tak naprawdę nie odpowiada na pytanie, dlaczego miałbyś używać obu; Odpowiedź jobrad jest dokładniejsza.
Miles
W przypadku Pythona 3.7 i Windows, realpath nie obsługuje podstawionych dysków, więc dla podstawionego dysku powiedz P: \, mając folder źródłowy c: \ MyFolder \ Bla, realpath zwraca P: \ not c: \ MyFolder \ Bla. Czy ktoś wie, jak zdobyć „prawdziwą” ścieżkę?
Totte Karlsson,
Dla mnie abspathnadal śledziłem dowiązania symboliczne, jeśli bieżący katalog jest dowiązaniem symbolicznym. Znalazłem tylko tę odpowiedź stackoverflow.com/questions/54665065/ ... aby zatrzymać to zachowanie.
Victor Sergienko
109

W twoim scenariuszu nie ma powodu, aby łączyć realpath i abspath, ponieważ w os.path.realpathrzeczywistości wywołuje os.path.abspathprzed zwróceniem wyniku (sprawdziłem Python 2.5 do Python 3.6).

  • os.path.abspath zwraca ścieżkę bezwzględną, ale NIE rozwiązuje dowiązań symbolicznych w swoim argumencie.
  • os.path.realpath najpierw rozwiąże wszystkie dowiązania symboliczne w ścieżce, a następnie zwróci ścieżkę bezwzględną.

Jeśli jednak spodziewasz się, że twoja ścieżka będzie zawierała a ~, ani abspath, ani realpath nie będą wskazywać ~katalogu domowego użytkownika, a wynikowa ścieżka będzie nieprawidłowa . Będziesz musiał użyć, os.path.expanduseraby rozwiązać ten problem z katalogiem użytkownika.

W celu dokładnego wyjaśnienia, oto kilka wyników, które zweryfikowałem w Windows i Linux, w Pythonie 3.4 i Pythonie 2.6. Bieżący katalog ( ./) to mój katalog domowy, który wygląda następująco:

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
źródło
3
Ładny. Aby zwrócić uwagę, ostatnim przykładem powinien byćos.path.realpath(os.path.expanduser('~/subdir/../data'))
Arthur,
3
W takim razie nie zapomnij o os.path.expandvars, jeśli w ścieżce są używane zmienne
Slavenskij
8

Mówiąc prościej, jeśli próbujesz uzyskać ścieżkę do pliku skrótu, ścieżka bezwzględna podaje pełną ścieżkę do pliku znajdującego się w lokalizacji skrótu , podczas gdy realpath podaje oryginalną ścieżkę do pliku.

Ścieżka bezwzględna, os.path.abspath (), podaje pełną ścieżkę do pliku, który znajduje się w bieżącym katalogu roboczym lub we wspomnianym katalogu.

Rzeczywista ścieżka, os.path.realpath (), podaje pełną ścieżkę do pliku, do którego się odnosi.

Na przykład:

file = "shortcut_folder/filename"
os.path.abspath(file) = "C:/Desktop/shortcut_folder/filename"
os.path.realpath(file) = "D:/PyCharmProjects/Python1stClass/filename"
ExtractTable.com
źródło