เหตุใดจึงใช้ทั้ง os.path.abspath และ os.path.realpath


102

ในโครงการโอเพนซอร์สหลายโครงการฉันเคยเห็นผู้คนทำ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เพียงแค่ลบสิ่งต่างๆเช่น.และ..ออกจากเส้นทางที่ให้เส้นทางแบบเต็มจากรากของแผนผังไดเรกทอรีไปยังไฟล์ที่มีชื่อ (หรือ symlink)

ตัวอย่างเช่นบน 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 สามารถมีพา ธ สัมพัทธ์ได้ดังนั้นจึงจำเป็นต้องใช้ทั้งสองอย่าง การเรียกภายในrealpathอาจส่งคืนเส้นทางที่มี..ชิ้นส่วนฝังอยู่ซึ่งabspathจะลบออก


10
แม้ว่าคำตอบนี้จะอธิบายถึงความแตกต่างระหว่างฟังก์ชันทั้งสอง แต่ก็ไม่เป็นความจริงที่ผลลัพธ์ของrealpath()can มี..ส่วนประกอบและไม่ได้ตอบคำถามว่าทำไมคุณถึงใช้ทั้งสองอย่าง คำตอบของ jobrad นั้นแม่นยำกว่า
ไมล์

สำหรับ Python 3.7 และ windows realpath ไม่เข้าใจไดรฟ์ที่ย่อยดังนั้นสำหรับไดรฟ์ที่ย่อยแล้วให้พูดว่า P: \ โดยมีโฟลเดอร์ต้นทาง c: \ MyFolder \ Bla, realpath จะส่งคืน P: \ not c: \ MyFolder \ Bla ใครรู้วิธีการได้รับ "เส้นทาง" จริง?
Totte Karlsson

สำหรับฉันabspathยังคงติดตาม symlink หากไดเร็กทอรีปัจจุบันเป็น symlink ฉันพบคำตอบนี้เท่านั้นstackoverflow.com/questions/54665065/…เพื่อหยุดพฤติกรรมนี้
Victor Sergienko

113

สำหรับสถานการณ์ที่คุณระบุไว้ไม่มีเหตุผลที่จะรวม 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'))
Arthur

4
จากนั้นอย่าลืมเกี่ยวกับ os.path.expandvars หากใช้ตัวแปรในเส้นทาง
Slavenskij

9

ในแง่ของคนธรรมดาถ้าคุณพยายามหาเส้นทางของไฟล์ทางลัดพา ธ สัมบูรณ์จะให้พา ธ ทั้งหมดของไฟล์ที่อยู่ในตำแหน่งทางลัดในขณะที่ 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"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.