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?
hobbes3
sumber
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 '..'.

forivall
sumber
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__)
locojay
sumber
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])  # "."
birnbaum
sumber
2
Ini jelas merupakan metode terbersih.
hobbes3
18

Anda menginginkan ini:

BASE_DIR = os.path.join( os.path.dirname( __file__ ), '..' )
Alan Viars
sumber
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())
Lord Sumner
sumber
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"

pythonBantuan Diperlukan
sumber
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.

Antony Hatchkins
sumber
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   
Marcus Krautwurst
sumber
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',
)
Haterh
sumber
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
Jo3l
sumber
0

Tentu saja: cukup gunakan os.chdir(..).

Shwarma
sumber
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')
abdullahselek
sumber