Menggunakan os.path Python, bagaimana cara naik satu direktori?


224

Saya baru-baru ini meningkatkan Django dari v1.3.1 ke v1.4.

Di masa lalu settings.pysaya miliki

TEMPLATE_DIRS = (
    os.path.join(os.path.dirname( __file__ ), 'templates').replace('\\', '/'),
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)

Ini akan menunjuk ke /Users/hobbes3/Sites/mysite/templates, tetapi karena Django v1.4 memindahkan folder proyek ke tingkat yang sama dengan folder aplikasi , settings.pyfile saya sekarang di /Users/hobbes3/Sites/mysite/mysite/bukan /Users/hobbes3/Sites/mysite/.

Jadi sebenarnya pertanyaan saya sekarang ada dua:

  1. Bagaimana cara saya os.pathmelihat direktori satu tingkat di atas __file__. Dengan kata lain, saya ingin /Users/hobbes3/Sites/mysite/mysite/settings.pymencari /Users/hobbes3/Sites/mysite/templatesmenggunakan jalur relatif.
  2. Haruskah saya menjaga templatefolder (yang memiliki cross-aplikasi template, seperti admin, registration, dll) di proyek /User/hobbes3/Sites/mysitetingkat atau /User/hobbes3/Sites/mysite/mysite?

Cant Anda hanya menggunakan osuntuk cdke ../mysite? Atau perintah apa pun yang Anda inginkan
prelic

@prelic Hmm? Saya tidak mengerti. Saya mencoba menghindari hardcoding path, karena saya menggunakan hal yang sama settings.pydi beberapa server. Satu-satunya perbedaan mungkin adalah kredensial basis data. Saya membaca os.pathdokumentasi tetapi saya tidak dapat menemukan perintah yang memungkinkan Anda naik satu direktori. Seperti cd ...
hobbes3

2
@ hobbes3 Anda bisa os.path.join( os.path.dirname( __file__ ), '..' ) ..berarti direktori di atas di seluruh sistem file, bukan hanya ketika diteruskan ke cd.
Michael Berkowski

3
@Michael, mungkin lebih baik menggunakanos.path.join( os.path.dirname ( __file__), os.path.pardir)
mgilson

Jawaban:


286
os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'templates'))

Sejauh mana folder templat harus pergi, saya tidak tahu karena Django 1.4 baru saja keluar dan saya belum melihatnya. Anda mungkin harus mengajukan pertanyaan lain pada SE untuk menyelesaikan masalah itu.

Anda juga dapat menggunakan normpathuntuk membersihkan jalur, bukan abspath. Namun, dalam situasi ini, Django mengharapkan jalur absolut daripada jalur relatif.

Untuk kompatibilitas lintas platform, gunakan os.pardirsebagai ganti '..'.


4
Apakah itu ide yang buruk untuk digunakan ..atau sesuatu? Mengapa jawaban ini mendapatkan lebih sedikit suara?
hobbes3

1
Saya tidak tahu mengapa suara itu berkurang, tetapi itulah yang selalu saya gunakan. Bahkan didefinisikan dalam contoh untuk normpath. Plus, itu akan melintasi symlink dengan benar.
forivall

1
Menggunakan abspath hanya akan sedikit membersihkannya. Jika tidak ada di sana, string sebenarnya untuk nama path akan /Users/hobbes3/Sites/mysite/mysite/../templates, yang benar-benar baik-baik saja, tetapi hanya sedikit lebih berantakan. Ini juga memastikan bahwa pengingat Django untuk menggunakan jalur absolut dipatuhi. Jika Anda berada dalam situasi berbeda yang menggunakan jalur relatif, Anda harus menggunakan normpath untuk menyederhanakan jalur Anda.
forivall

2
Pertanyaan ini baru saja diajukan mengenai migrasi struktur folder untuk versi baru Django , jadi Anda mungkin harus melihat itu untuk menyelesaikan masalah kedua Anda.
forivall

1
@Zitrax Apakah Anda tahu ada platform di mana ini akan berbeda, atau itu hanya ada untuk keselamatan di masa depan? (Saya tidak benar-benar tahu tentang os.pardir, tidak pernah benar-benar sampai ke bagian bawah osdokumen)
forivall

98

Untuk mendapatkan folder file cukup gunakan:

os.path.dirname(path) 

Untuk mendapatkan folder cukup gunakan os.path.dirnamelagi

os.path.dirname(os.path.dirname(path))

Anda mungkin ingin memeriksa apakah __file__symlink:

if os.path.islink(__file__): path = os.readlink (__file__)

17
Apakah ada cara untuk membuka nfolder tanpa harus memanggil os.path.dirname nwaktu?
Oriol Nieto

9
@OriolNieto Ya, seperti versi Python 3.4+ yang dapat Anda gunakan pathlib.Path.parents[levels_up-1]. Lihat pertanyaan ini untuk solusi lebih lanjut
jwalton

23

Jika Anda menggunakan Python 3.4 atau yang lebih baru, cara mudah untuk naik ke beberapa direktori adalah pathlib:

from pathlib import Path

full_path = "path/to/directory"
str(Path(full_path).parents[0])  # "path/to"
str(Path(full_path).parents[1])  # "path"
str(Path(full_path).parents[2])  # "."

2
Ini jelas merupakan metode terbersih.
hobbes3

18

Anda menginginkan ini:

BASE_DIR = os.path.join( os.path.dirname( __file__ ), '..' )

9

Secara pribadi, saya akan pergi untuk pendekatan fungsi

def get_parent_dir(directory):
    import os
    return os.path.dirname(directory)

current_dirs_parent = get_parent_dir(os.getcwd())

Hati-hati jawaban ini tidak berfungsi jika input berisi garis miring, misalnya os.path.dirname('/tmp/lala/')masih kembali'/tmp/lala'
Buah

Kasus garis miring dapat merujuk jawaban ini: stackoverflow.com/a/25669963/1074998
Fruit

7

Saya pikir hal termudah untuk dilakukan adalah hanya menggunakan kembali dirname () Jadi Anda dapat menelepon

os.path.dirname(os.path.dirname( __file__ ))

jika file Anda di / Pengguna / host3/Situs/mysite/templates/method.py

Ini akan mengembalikan "/ Pengguna / hobbes3 / Situs / situs saya"


6
from os.path import dirname, realpath, join
join(dirname(realpath(dirname(__file__))), 'templates')

Memperbarui:

Jika Anda kebetulan "menyalin" settings.pymelalui symlinking, jawaban @ forivall lebih baik:

~user/
    project1/  
        mysite/
            settings.py
        templates/
            wrong.html

    project2/
        mysite/
            settings.py -> ~user/project1/settings.py
        templates/
            right.html

Metode di atas akan 'melihat' wrong.htmlsedangkan metode @ forivall akan melihatright.html

Dalam ketiadaan symlinks dua jawaban identik.


Apakah ada yang salah dengan pendekatan ini? Ini berfungsi dengan baik dan terlihat bagus tetapi sedikit
retas

Ini sedikit berbeda dari jawaban yang diterima dalam cara berurusan dengan tautan. Mereka identik sebaliknya.
Antony Hatchkins

6

Ini mungkin berguna untuk kasus lain di mana Anda ingin naik x folder. Jalankan saja walk_up_folder(path, 6)untuk naik 6 folder.

def walk_up_folder(path, depth=1):
    _cur_depth = 1        
    while _cur_depth < depth:
        path = os.path.dirname(path)
        _cur_depth += 1
    return path   

Hanya bisa menggunakan for _ in xrange(depth)alih-alih melacak variabel lokal.
Zitrax

2

Untuk paranoid seperti saya, saya lebih suka yang ini

TEMPLATE_DIRS = (
    __file__.rsplit('/', 2)[0] + '/templates',
)

8
mungkin alih-alih '/'Anda harus menggunakanos.sep
djhaskin987

1

Untuk membuka nfolder ... jalankanup(n)

import os

def up(n, nth_dir=os.getcwd()):
    while n != 0:
        nth_dir = os.path.dirname(nth_dir)
        n -= 1
    return nth_dir


0

Dengan menggunakan os.pathkita bisa pergi satu direktori seperti itu

one_directory_up_path = os.path.dirname('.')

juga setelah menemukan direktori yang Anda inginkan, Anda dapat bergabung dengan jalur file / direktori lainnya

other_image_path = os.path.join(one_directory_up_path, 'other.jpg')
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.