Mengapa seseorang menggunakan keduanya, os.path.abspath dan os.path.realpath?

98

Dalam beberapa proyek open source, saya telah melihat orang-orang melakukannya os.path.abspath(os.path.realpath(__file__))untuk mendapatkan jalur absolut ke file saat ini.

Namun, saya menemukannya os.path.abspath(__file__)dan os.path.realpath(__file__)menghasilkan hasil yang sama. os.path.abspath(os.path.realpath(__file__))tampaknya agak berlebihan.

Apakah ada alasan orang menggunakan itu?

hch
sumber

Jawaban:

66

os.path.realpath membedakan tautan simbolis pada sistem operasi yang mendukungnya.

os.path.abspathcukup menghapus hal-hal seperti .dan ..dari jalur yang memberikan jalur lengkap dari akar pohon direktori ke file bernama (atau symlink)

Misalnya, di 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'

Symlinks dapat berisi jalur relatif, karenanya perlu menggunakan keduanya. Panggilan batin ke realpathmungkin mengembalikan jalur dengan ..bagian yang disematkan , yang abspathkemudian dihapus.

kdopen
sumber
10
Meskipun jawaban ini menjelaskan perbedaan antara kedua fungsi tersebut, tidak benar bahwa hasil dari realpath()can berisi ..komponen dan tidak benar-benar menjawab pertanyaan mengapa Anda akan menggunakan keduanya; Jawaban jobrad lebih akurat.
Miles
Untuk Python 3.7 dan windows, realpath tidak mengerti drive substed. Jadi untuk drive substed, katakanlah P: \, memiliki folder sumber c: \ MyFolder \ Bla, realpath mengembalikan P: \ bukan c: \ MyFolder \ Bla. Adakah yang tahu bagaimana mendapatkan jalan yang "sebenarnya"?
Totte Karlsson
Bagi saya, abspathmasih mengikuti symlink jika direktori saat ini adalah symlink. Saya hanya menemukan jawaban stackoverflow.com/questions/54665065/… ini untuk menghentikan perilaku ini.
Victor Sergienko
108

Untuk skenario yang Anda nyatakan, tidak ada alasan untuk menggabungkan realpath dan abspath, karena os.path.realpathsebenarnya memanggil os.path.abspathsebelum mengembalikan hasil (saya memeriksa Python 2.5 ke Python 3.6).

  • os.path.abspath mengembalikan jalur absolut, tetapi TIDAK menyelesaikan symlink dalam argumennya.
  • os.path.realpath pertama-tama akan menyelesaikan semua tautan simbolis di jalur, dan kemudian mengembalikan jalur absolut.

Namun, jika Anda mengharapkan jalur berisi a ~, baik abspath atau realpath tidak akan menyelesaikan ~direktori beranda pengguna, dan jalur yang dihasilkan tidak valid . Anda perlu menggunakan os.path.expanduseruntuk menyelesaikan ini ke direktori pengguna.

Demi penjelasan lengkap, berikut adalah beberapa hasil yang telah saya verifikasi di Windows dan Linux, dengan Python 3.4 dan Python 2.6. Direktori saat ini ( ./) adalah direktori home saya, yang terlihat seperti ini:

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
sumber
3
Bagus. Untuk membuat poin Anda, contoh terakhir Anda seharusnyaos.path.realpath(os.path.expanduser('~/subdir/../data'))
Arthur
3
Kemudian juga jangan lupa tentang os.path.expandvars jika variabel digunakan di jalur
Slavenskij
8

Dalam istilah awam, jika Anda mencoba mendapatkan jalur file pintasan, jalur absolut memberikan jalur lengkap dari file yang ada di lokasi pintasan , sedangkan realpath memberikan jalur lokasi asli dari file tersebut.

Path absolut, os.path.abspath (), memberikan path lengkap dari file yang terletak di direktori kerja saat ini atau direktori yang Anda sebutkan.

Path nyata, os.path.realpath (), memberikan path lengkap dari file yang dirujuk.

Misalnya:

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