รหัสด้านล่างจะไม่เข้าร่วมเมื่อทำการดีบั๊กคำสั่งจะไม่เก็บเส้นทางทั้งหมด แต่เป็นเพียงรายการสุดท้าย
os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
เมื่อฉันทดสอบสิ่งนี้จะเก็บเฉพาะ/new_sandbox/
ส่วนของรหัสเท่านั้น
รหัสด้านล่างจะไม่เข้าร่วมเมื่อทำการดีบั๊กคำสั่งจะไม่เก็บเส้นทางทั้งหมด แต่เป็นเพียงรายการสุดท้าย
os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')
เมื่อฉันทดสอบสิ่งนี้จะเก็บเฉพาะ/new_sandbox/
ส่วนของรหัสเท่านั้น
คำตอบ:
สตริงหลังไม่ควรเริ่มต้นด้วยเครื่องหมายทับ หากพวกเขาเริ่มต้นด้วยการเฉือนแล้วพวกเขาก็ถือว่าเป็น "เส้นทางที่แน่นอน" และทุกอย่างก่อนที่พวกเขาจะถูกทิ้ง
การอ้างอิงเอกสาร Python สำหรับos.path.join
:
หากส่วนประกอบคือพา ธ สัมบูรณ์ส่วนประกอบก่อนหน้านี้ทั้งหมดจะถูกโยนทิ้งไปและการเข้าร่วมจะดำเนินต่อจากส่วนประกอบพา ธ สัมบูรณ์
หมายเหตุเกี่ยวกับ Windows พฤติกรรมที่เกี่ยวข้องกับตัวอักษรไดรฟ์ซึ่งดูเหมือนว่าจะมีการเปลี่ยนแปลงเมื่อเทียบกับรุ่น Python รุ่นก่อนหน้า:
ใน Windows อักษรชื่อไดรฟ์จะไม่ถูกรีเซ็ตเมื่อพบส่วนประกอบของเส้นทางที่แน่นอน (เช่น
r'\foo'
) หากส่วนประกอบมีตัวอักษรชื่อไดรฟ์ส่วนประกอบก่อนหน้านี้ทั้งหมดจะถูกโยนทิ้งไปและตัวอักษรไดรฟ์จะถูกรีเซ็ต โปรดทราบว่าเนื่องจากมีไดเรกทอรีปัจจุบันสำหรับแต่ละไดรฟ์os.path.join("c:", "foo")
แสดงเส้นทางที่สัมพันธ์กับไดเรกทอรีปัจจุบันบนไดรฟ์C:
(c:foo
)c:\foo
ไม่ได้
os.path.normpath
เพื่อให้บรรลุเป้าหมายนั้น
แนวคิดของos.path.join()
การทำให้โปรแกรมของคุณข้ามแพลตฟอร์ม (linux / windows / etc)
แม้แต่สแลชที่หักพังก็ยังมีอยู่
ดังนั้นก็เพียงทำให้รู้สึกเมื่อมีการใช้กับชนิดของจุดอ้างอิงเช่นบาง
หรือos.environ['HOME']
os.path.dirname(__file__)
os.path.join()
สามารถใช้ร่วมกับos.path.sep
เพื่อสร้างสัมบูรณ์มากกว่าเส้นทางสัมพัทธ์
os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')
os.path.sep
เป็นองค์ประกอบแรกในการสร้างเส้นทางที่แน่นอนดีกว่าคำตอบอื่น ๆ ที่นี่! จุดรวมของการใช้os.path
มากกว่าวิธี STR /
พื้นฐานคือการหลีกเลี่ยงการเขียน การใส่ทุกไดเรกทอรีย่อยเป็นอาร์กิวเมนต์ใหม่และลบเครื่องหมายทับทั้งหมดก็ยอดเยี่ยมเช่นกัน มันอาจจะเป็นความคิดที่ดีที่จะตรวจสอบให้แน่ใจด้วยเช็คที่todaystr
ไม่ได้เริ่มต้นด้วยเครื่องหมายทับ! ;)
อย่าใช้ฟอร์เวิร์ดสแลชที่จุดเริ่มต้นของคอมโพเนนต์พา ธ ยกเว้นเมื่ออ้างถึงไดเร็กทอรีรูท:
os.path.join('/home/build/test/sandboxes', todaystr, 'new_sandbox')
ดูเพิ่มเติมที่: http://docs.python.org/library/os.path.html#os.path.join
ที่จะช่วยให้เข้าใจว่าทำไมพฤติกรรมที่น่าแปลกใจนี้ไม่ได้อย่างสิ้นเชิงสาหัสพิจารณาใบสมัครที่รับชื่อไฟล์ config เป็นอาร์กิวเมนต์นี้:
config_root = "/etc/myapp.conf/"
file_name = os.path.join(config_root, sys.argv[1])
หากแอปพลิเคชันทำงานด้วย:
$ myapp foo.conf
ไฟล์กำหนดค่า/etc/myapp.conf/foo.conf
จะถูกใช้
แต่ให้พิจารณาว่าจะเกิดอะไรขึ้นหากแอปพลิเคชันถูกเรียกด้วย:
$ myapp /some/path/bar.conf
จากนั้นmyapp
ควรใช้ไฟล์กำหนดค่าที่/some/path/bar.conf
(และไม่/etc/myapp.conf/some/path/bar.conf
เหมือนกัน)
มันอาจจะไม่ดีนัก แต่ฉันเชื่อว่านี่เป็นแรงบันดาลใจสำหรับพฤติกรรมเส้นทางที่สมบูรณ์
เป็นเพราะคุณ'/new_sandbox/'
เริ่มต้นด้วยการ/
และถือว่าเป็นญาติกับไดเรกทอรีราก นำ/
หน้า
ในการทำให้ฟังก์ชั่นของคุณพกพาได้สะดวกยิ่งขึ้นให้ใช้:
os.path.join(os.sep, 'home', 'build', 'test', 'sandboxes', todaystr, 'new_sandbox')
หรือ
os.path.join(os.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')
ลองใช้คำสั่งผสมsplit("/")
และ*
สำหรับสตริงที่มีการรวมที่มีอยู่
import os
home = '/home/build/test/sandboxes/'
todaystr = '042118'
new = '/new_sandbox/'
os.path.join(*home.split("/"), todaystr, *new.split("/"))
มันทำงานอย่างไร...
split("/")
เปลี่ยนเส้นทางที่มีอยู่เป็นรายการ: ['', 'home', 'build', 'test', 'sandboxes', '']
*
ที่ด้านหน้าของรายการแบ่งแต่ละรายการของรายการพารามิเตอร์ของตัวเอง
ลองด้วยnew_sandbox
เท่านั้น
os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox')
ทำเช่นนี้ได้โดยไม่ต้องทับทับมากเกินไป
root="/home"
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox")
โปรดทราบว่าปัญหาที่คล้ายกันสามารถกัดคุณถ้าคุณใช้จะมีส่วนขยายที่มีอยู่แล้วรวมถึงจุดซึ่งเป็นสิ่งที่เกิดขึ้นโดยอัตโนมัติเมื่อคุณใช้os.path.join()
os.path.splitext()
ในตัวอย่างนี้:
components = os.path.splitext(filename)
prefix = components[0]
extension = components[1]
return os.path.join("avatars", instance.username, prefix, extension)
แม้ว่าคุณextension
จะ.jpg
ท้ายด้วยโฟลเดอร์ชื่อ "foobar" แทนที่จะเป็นไฟล์ชื่อ "foobar.jpg" เพื่อป้องกันสิ่งนี้คุณต้องผนวกส่วนขยายแยกต่างหาก:
return os.path.join("avatars", instance.username, prefix) + extension
คุณสามารถ:strip
'/'
>>> os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/'.strip('/'))
'/home/build/test/sandboxes/04122019/new_sandbox'
ฉันขอแนะนำให้ตัดจากที่สองและสตริงต่อไปนี้สายos.path.sep
ป้องกันไม่ให้พวกเขาถูกตีความว่าเป็นเส้นทางที่แน่นอน:
first_path_str = '/home/build/test/sandboxes/'
original_other_path_to_append_ls = [todaystr, '/new_sandbox/']
other_path_to_append_ls = [
i_path.strip(os.path.sep) for i_path in original_other_path_to_append_ls
]
output_path = os.path.join(first_path_str, *other_path_to_append_ls)
os.path.join("a", *"/b".split(os.sep))
'a/b'
เวอร์ชันเต็ม:
import os
def join (p, f, sep = os.sep):
f = os.path.normpath(f)
if p == "":
return (f);
else:
p = os.path.normpath(p)
return (os.path.join(p, *f.split(os.sep)))
def test (p, f, sep = os.sep):
print("os.path.join({}, {}) => {}".format(p, f, os.path.join(p, f)))
print(" join({}, {}) => {}".format(p, f, join(p, f, sep)))
if __name__ == "__main__":
# /a/b/c for all
test("\\a\\b", "\\c", "\\") # optionally pass in the sep you are using locally
test("/a/b", "/c", "/")
test("/a/b", "c")
test("/a/b/", "c")
test("", "/c")
test("", "c")
"\"
? จากนั้นตัวอย่างแรกของคุณจะกลายเป็นos.path.join("a", *"/b".split("\\"))
ซึ่งให้ผลผลิต"/b"
... ฉันสงสัยว่าเป็นผลลัพธ์ที่ตั้งใจไว้