วิธีการรับตำแหน่ง dir หลัก


131

รหัสนี้ได้รับ template / blog1 / page.html ใน b.py:

path = os.path.join(os.path.dirname(__file__), os.path.join('templates', 'blog1/page.html'))

แต่ฉันต้องการรับตำแหน่ง dir หลัก:

aParent
   |--a
   |  |---b.py
   |      |---templates
   |              |--------blog1
   |                         |-------page.html
   |--templates
          |--------blog1
                     |-------page.html

และวิธีรับตำแหน่งผู้ปกครอง

ขอบคุณ

updated:

ถูกต้องแล้ว:

dirname=os.path.dirname
path = os.path.join(dirname(dirname(__file__)), os.path.join('templates', 'blog1/page.html'))

หรือ

path = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))

2
คุณต้องการที่จะได้รับblog1หรือa? และไฟล์ปัจจุบันของคุณอยู่ที่ไหน?
Felix Kling

คุณเข้าใจหรือไม่ว่าโค้ดของคุณกำลังทำอะไรอยู่
SilentGhost

1
ใช่มันได้รับแม่แบบ / blog1 / page.html
zjm1126

os.path.join('templates', 'blog1/page.html')ดูแปลกสำหรับฉัน คุณกำลังผสมสิ่งต่างๆ อย่างใดอย่างหนึ่งos.path.join('templates', 'blog1', 'page.html')หรือ'templates/blog1/page.html'. และจะง่ายกว่าos.path.abspath(os.path.join('templates', 'blog1', 'page.html'))นั้นมาก
Felix Kling

1
@zjm: ไม่คุณไม่ได้รับหน้านั้น ไม่ใช่ blackbox ที่คุณสามารถใช้เพื่อรับไฟล์เทมเพลตได้ มันดำเนินการขั้นตอนเล็ก ๆ น้อย ๆ หลายขั้นตอนและถ้าคุณเข้าใจได้คุณก็จะไม่มีคำถามนี้
SilentGhost

คำตอบ:


173

คุณสามารถใช้ dirname ซ้ำ ๆ dirname(dirname(file))ที่จะปีนขึ้นไป: อย่างไรก็ตามสิ่งนี้สามารถไปได้ไกลถึงแพ็กเกจรูทเท่านั้น หากเป็นปัญหาให้ใช้os.path.abspath: dirname(dirname(abspath(file))).


37
ฉันรู้ว่า OP dirnameรู้เกี่ยวกับ ทุกคนไม่ชัดเจนว่าการใช้ dirname กับไดเร็กทอรีจะทำให้ไดเร็กทอรีหลัก
Marcelo Cantos

4
dirnameไม่ไม่เสมอกลับไดเรกทอรีแม่; twitter.com/#!/ActiveState/status/671049326788608
Sridhar Ratnakumar

2
@Sridhar: ขึ้นอยู่กับมุมมองของคุณ ฉันพิจารณาว่าพา ธ ที่ลงท้ายด้วย/ไม่ได้แสดงถึงรายการไดเร็กทอรี leaf แต่เนื้อหาซึ่งเป็นสาเหตุเช่นmv xxx yyy/ล้มเหลวหากyyyไม่ใช่ไดเร็กทอรีที่มีอยู่ก่อน ไม่ว่าในกรณีใดก็ตามแม้ว่าเราจะใช้ประเด็นของคุณเป็นจุดที่กำหนด แต่ก็ไม่เกี่ยวข้องในบริบทของคำตอบของฉัน ทั้งสองfileและผลลัพธ์ของdirnameจะไม่จบลงด้วย/.
Marcelo Cantos

1
การแก้ไขเล็กน้อย: dirnameอาจกลับมา'/'ซึ่งลงท้ายด้วย/. นั่นเป็นข้อยกเว้นเพียงอย่างเดียว AFAIK
Marcelo Cantos

55

os.path.abspathไม่ได้ตรวจสอบความถูกต้องใด ๆ ดังนั้นหากเราต่อท้ายสตริงอยู่แล้ว__file__ก็ไม่จำเป็นต้องกังวลกับการdirnameเข้าร่วมหรือใด ๆ เพียงแค่ใช้__file__เป็นไดเรกทอรีและเริ่มปีนเขา:

# climb to __file__'s parent's parent:
os.path.abspath(__file__ + "/../../")

ที่ซับซ้อนน้อยกว่าและเรื่องเกี่ยวกับการจัดการที่เป็นos.path.abspath(os.path.join(os.path.dirname(__file__),"..")) dirname(dirname(__file__))การปีนมากกว่าสองระดับเริ่มไร้สาระ

แต่เนื่องจากเรารู้ว่าต้องไต่ระดับกี่ระดับเราจึงสามารถทำความสะอาดสิ่งนี้ได้ด้วยฟังก์ชั่นเล็ก ๆ ง่ายๆ:

uppath = lambda _path, n: os.sep.join(_path.split(os.sep)[:-n])

# __file__ = "/aParent/templates/blog1/page.html"
>>> uppath(__file__, 1)
'/aParent/templates/blog1'
>>> uppath(__file__, 2)
'/aParent/templates'
>>> uppath(__file__, 3)
'/aParent'

2
นี่เป็นสิ่งที่ดี แต่ก็จะดีเช่นกันถ้าห้องสมุดมาตรฐานเพิ่มฟังก์ชันอำนวยความสะดวกที่ทำได้สำเร็จ ... ไม่อยากมา SO ทุกครั้งที่ฉันต้องการฟังก์ชั่นนี้
gradi3nt

4
จะos.path.abspath(os.path.join(__file__, "..", "..")พกพาสะดวกกว่าไหม
slowD

40

ใช้เส้นทางสัมพัทธ์กับpathlibโมดูลใน Python 3.4+:

from pathlib import Path

Path(__file__).parent

คุณสามารถใช้การโทรหลายครั้งparentเพื่อไปต่อในเส้นทาง:

Path(__file__).parent.parent

เป็นทางเลือกให้ระบุparentสองครั้งคุณสามารถใช้:

Path(__file__).parents[1]

2
หากคุณต้องการเส้นทางเป็นสตริงเนื่องจากคุณต้องการแก้ไขคุณสามารถใช้str(Path(__file__).parent)ไฟล์.
Philipp

12
os.path.dirname(os.path.abspath(__file__))

ควรให้เส้นทางไปa.

แต่ถ้าb.pyเป็นไฟล์ที่กำลังดำเนินการอยู่คุณสามารถทำได้โดยทำเพียงแค่

os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))

1
ฉันรู้ว่าคุณพูดถูกและฉันต้องการรับโฟลเดอร์หลักของ a วิธีการรับ
zjm1126

@ zjm1126: ดูคำตอบของ Marcelo Cantos สมัครdirname()สองครั้ง ทุกสิ่งที่คุณต้องการตอนนี้ควรอยู่ในไซต์นี้
Felix Kling

9

os.pardirเป็นวิธีที่ดีกว่า../และอ่านง่ายขึ้น

import os
print os.path.abspath(os.path.join(given_path, os.pardir))  

สิ่งนี้จะส่งคืนพา ธ หลักของ given_path



3

อาจจะเข้าร่วมสอง..โฟลเดอร์เพื่อรับหลักของโฟลเดอร์หลัก?

path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),"..",".."))

3

ใช้สิ่งต่อไปนี้เพื่อข้ามไปยังโฟลเดอร์ก่อนหน้า:

os.chdir(os.pardir)

หากคุณต้องการกระโดดหลาย ๆ ครั้งวิธีแก้ปัญหาที่ดีและง่ายคือการใช้มัณฑนากรแบบธรรมดาในกรณีนี้


1

นี่เป็นอีกวิธีหนึ่งที่ค่อนข้างง่าย:

  • ไม่ใช้dirname()(ซึ่งไม่ได้ผลตามที่คาดไว้ในอาร์กิวเมนต์ระดับเดียวเช่น "file.txt" หรือผู้ปกครองที่เป็นญาติเช่น ".. ")
  • ไม่ใช้abspath()(หลีกเลี่ยงสมมติฐานใด ๆ เกี่ยวกับไดเร็กทอรีการทำงานปัจจุบัน) แต่จะรักษาลักษณะสัมพัทธ์ของพา ธ แทน

มันใช้normpathและjoin:

def parent(p):
    return os.path.normpath(os.path.join(p, os.path.pardir))

# Example:
for p in ['foo', 'foo/bar/baz', 'with/trailing/slash/', 
        'dir/file.txt', '../up/', '/abs/path']:
    print parent(p)

ผลลัพธ์:

.
foo/bar
with/trailing
dir
..
/abs

0

ฉันคิดว่าใช้สิ่งนี้ดีกว่า:

os.path.realpath(__file__).rsplit('/', X)[0]


In [1]: __file__ = "/aParent/templates/blog1/page.html"

In [2]: os.path.realpath(__file__).rsplit('/', 3)[0]
Out[3]: '/aParent'

In [4]: __file__ = "/aParent/templates/blog1/page.html"

In [5]: os.path.realpath(__file__).rsplit('/', 1)[0]
Out[6]: '/aParent/templates/blog1'

In [7]: os.path.realpath(__file__).rsplit('/', 2)[0]
Out[8]: '/aParent/templates'

In [9]: os.path.realpath(__file__).rsplit('/', 3)[0]
Out[10]: '/aParent'

ไม่มากมันขึ้นอยู่กับระบบปฏิบัติการ (จะไม่ทำงานบน Windows) นอกจากนี้ยังไม่อนุญาตให้ใช้เส้นทางสัมพัทธ์
kgadek

นั่นเป็นทางออกที่แย่มาก ใช้ไม่ได้กับทุกระบบปฏิบัติการ
web.learner

0

ฉันเหนื่อย:

import os
os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))), os.pardir))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.