Cara mendapatkan lokasi dir induk


131

kode ini adalah templat / blog1 / page.html di b.py:

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

tetapi saya ingin mendapatkan lokasi dir induk:

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

dan cara mendapatkan lokasi aParent

Terima kasih

diperbarui:

ini benar:

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

atau

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

2
Jadi, Anda ingin mendapatkan blog1atau a? Dan di mana file Anda saat ini berada?
Felix Kling

apakah Anda mengerti apa yang kode Anda lakukan?
SilentGhost

1
ya, itu mendapatkan templat / blog1 / page.html
zjm1126

os.path.join('templates', 'blog1/page.html')terlihat aneh bagiku. Anda mencampuradukkan hal-hal. Entah os.path.join('templates', 'blog1', 'page.html')atau 'templates/blog1/page.html'. Dan jauh lebih mudah kalau os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))begitu
Felix Kling

1
@ zjm: tidak, Anda tidak mendapatkan halaman itu. Ini bukan kotak hitam yang bisa Anda gunakan untuk mendapatkan file templat. Ia melakukan serangkaian langkah-langkah kecil yang sepele, dan jika Anda bisa memahaminya, Anda tidak akan memiliki pertanyaan ini.
SilentGhost

Jawaban:


173

Anda dapat menerapkan dirname berulang kali untuk naik lebih tinggi: dirname(dirname(file)). Ini hanya bisa sejauh paket root, namun. Jika ini adalah masalah, gunakan os.path.abspath: dirname(dirname(abspath(file))).


37
Saya tahu OP tahu tentang dirname. Tidak jelas bagi semua orang bahwa menerapkan dirname ke direktori menghasilkan direktori induk.
Marcelo Cantos

4
dirnametidak tidak selalu mengembalikan direktori induk; twitter.com/#!/ActiveState/status/671049326788608
Sridhar Ratnakumar

2
@Ridhar: Itu tergantung pada perspektif Anda; Saya menganggap jalan berakhir /sebagai tidak mewakili entri direktori daun itu sendiri, tetapi isinya, itulah sebabnya, misalnya, mv xxx yyy/gagal jika yyybukan direktori yang sudah ada sebelumnya. Dalam kasus apa pun, bahkan jika kami menganggap pendapat Anda sebagai yang diberikan, itu tidak relevan dalam konteks jawaban saya. Baik filehasil dari dirnameakan pernah berakhir dengan /.
Marcelo Cantos

1
Koreksi kecil: dirnamedapat kembali '/', yang jelas berakhir dengan a /. Itulah satu-satunya pengecualian, AFAIK.
Marcelo Cantos

55

os.path.abspathtidak memvalidasi apa pun, jadi jika kita sudah menambahkan string ke __file__tidak perlu repot dengan dirnameatau bergabung atau apa pun. Cukup perlakukan __file__sebagai direktori dan mulailah mendaki:

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

Itu jauh lebih berbelit-belit daripada os.path.abspath(os.path.join(os.path.dirname(__file__),".."))sekitar bisa dikelola dirname(dirname(__file__)). Mendaki lebih dari dua tingkat mulai menjadi konyol.

Tapi, karena kita tahu berapa level yang harus didaki, kita bisa membersihkannya dengan fungsi kecil sederhana:

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
Ini bagus, tetapi juga akan keren jika perpustakaan standar menambahkan fungsi kenyamanan yang menyelesaikan ini ... tidak ingin datang ke SO setiap kali saya membutuhkan fungsi ini
gradi3nt

4
Akan os.path.abspath(os.path.join(__file__, "..", "..")lebih portabel?
slowD

40

Gunakan jalur relatif dengan pathlibmodul dalam Python 3.4+:

from pathlib import Path

Path(__file__).parent

Anda dapat menggunakan beberapa panggilan parentuntuk melangkah lebih jauh di jalur:

Path(__file__).parent.parent

Sebagai alternatif untuk menetapkan parentdua kali, Anda dapat menggunakan:

Path(__file__).parents[1]

2
Jika Anda memerlukan path sebagai string karena Anda ingin memodifikasinya, Anda bisa menggunakannya str(Path(__file__).parent).
Philipp

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

Harus memberi Anda jalan ke a.

Tetapi jika b.pyfile yang sedang dieksekusi, maka Anda dapat mencapai hal yang sama dengan hanya melakukan

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

1
o, saya tahu, Anda benar, dan saya ingin mendapatkan folder induk a. bagaimana cara mendapatkannya
zjm1126

@ zjm1126: Lihat jawaban Marcelo Cantos. Terapkan dirname()dua kali. Semua yang Anda butuhkan sekarang harus ada di situs ini.
Felix Kling

9

os.pardiradalah cara yang lebih baik ../dan lebih mudah dibaca.

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

Ini akan mengembalikan path induk dari given_path


5

Cara sederhana dapat:

import os
current_dir =  os.path.abspath(os.path.dirname(__file__))
parent_dir = os.path.abspath(current_dir + "/../")
print parent_dir

3

Bisa gabung dua ..folder, untuk mendapatkan induk dari folder induk?

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

3

Gunakan yang berikut untuk melompat ke folder sebelumnya:

os.chdir(os.pardir)

Jika Anda membutuhkan beberapa lompatan, solusi yang baik dan mudah adalah menggunakan dekorator sederhana dalam kasus ini.


1

Berikut ini adalah solusi lain yang relatif sederhana yaitu:

  • tidak menggunakan dirname()(yang tidak berfungsi seperti yang diharapkan pada argumen satu tingkat seperti "file.txt" atau orang tua relatif seperti "..")
  • tidak menggunakan abspath()(menghindari asumsi tentang direktori kerja saat ini) tetapi malah mempertahankan karakter relatif dari path

hanya menggunakan normpathdan 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)

Hasil:

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

0

Saya pikir menggunakan ini lebih baik:

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'

Tidak cukup, itu tergantung OS (tidak akan bekerja di Windows). Juga tidak memungkinkan untuk menggunakan jalur relatif.
kgadek

Itu solusi yang mengerikan. Tidak akan bekerja untuk semua OS
web.learner

0

Saya mencoba:

import os
os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))), os.pardir))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.