Python's os.path kullanarak bir dizine nasıl çıkarım?


224

Son zamanlarda Django'yu v1.3.1'den v1.4'e yükselttim.

Benim eski yılında settings.pyI var

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.
)

Bu işaret eder /Users/hobbes3/Sites/mysite/templates, fakat Django v1.4 uygulaması klasörler ile aynı seviyeye proje klasörü taşındı çünkü , benim settings.pydosya artık /Users/hobbes3/Sites/mysite/mysite/yerine /Users/hobbes3/Sites/mysite/.

Aslında benim sorum şimdi iki yönlü:

  1. os.pathBir seviye üstteki dizine bakmak için nasıl kullanılır __file__? Başka bir deyişle, göreli yollar kullanarak /Users/hobbes3/Sites/mysite/mysite/settings.pybulmak istiyorum /Users/hobbes3/Sites/mysite/templates.
  2. Ben tutarak olmalı template(çapraz uygulama şablonları gibi sahip klasörü admin, registrationproje, vs.) /User/hobbes3/Sites/mysitedüzeyinde ya da /User/hobbes3/Sites/mysite/mysite?

Sadece cant'kullanma osiçin cdiçin ../mysite? Veya ne istersen
ver

@prelic Hmm? Anlamıyorum. settings.pyBirden fazla sunucuda aynı kullandığım için yolu kodlamadan kaçınmaya çalışıyorum . Tek fark veritabanı kimlik bilgileri olabilir. os.pathBelgeleri okuyordum ama bir dizine çıkmanıza izin veren bir komut bulamadım. Gibi cd ...
hobbes3

2
@ hobbes3 Yalnızca dosya sistemine geçildiğinde değil, dosya sistemi boyunca yukarıdaki dizinos.path.join( os.path.dirname( __file__ ), '..' ) .. anlamına da gelebilirsiniz cd.
Şubat 12'de Michael Berkowski

3
@Michael, muhtemelen daha iyios.path.join( os.path.dirname ( __file__), os.path.pardir)
mgilson

Yanıtlar:


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

Şablonlar klasörünün nereye gitmesi gerektiği konusunda, Django 1.4 yeni çıktığı için henüz bilmiyorum ve henüz bakmadım. Bu sorunu çözmek için muhtemelen SE konusunda başka bir soru sormalısınız.

Ayrıca normpathyolu temizlemek için de kullanabilirsiniz abspath. Ancak, bu durumda, Django göreceli bir yol yerine mutlak bir yol bekler.

Platformlar arası uyumluluk için os.pardiryerine kullanın '..'.


4
Kullanmak kötü bir fikir ..mi yoksa başka bir şey mi? Bu cevap neden daha az oy alıyor?
hobbes3

1
Neden daha az oy aldığını bilmiyorum, ama her zaman kullandım. Hatta bu örnekte tanımlanmıştır normpath. Ayrıca, sembolik bağlantıları düzgün bir şekilde geçecektir.
forivall

1
Abspath kullanmak onu biraz temizleyecektir. Orada değilse, yol adı için gerçek dize olacaktır /Users/hobbes3/Sites/mysite/mysite/../templates, bu da gayet iyi, ancak biraz daha dağınık. Ayrıca, Django'nun mutlak yolları kullanma hatırlatmasına uyulmasını sağlar. Göreli bir yol kullanan farklı bir durumdaysanız, bunun yerine yollarınızı basitleştirmek için normpath kullanmanız gerekir.
forivall

2
Bu soru yeni Django'nun yeni sürümü için klasör yapısının taşınmasıyla ilgili olarak sorulmuştur , bu nedenle muhtemelen ikinci sorununuzu çözmek için buna bakmalısınız.
forivall

1
@Zitrax Bunun farklı olacağı platformlar biliyor musunuz, yoksa gelecekteki güvenlik için orada mı? (Aslında bilmiyordum os.pardir, aslında osbelgelerin dibine hiç
gelmedim

98

Bir dosyanın klasörünü almak için şunu kullanın:

os.path.dirname(path) 

Bir klasörü almak için os.path.dirnametekrar kullanın

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

__file__Bir symlink olup olmadığını kontrol etmek isteyebilirsiniz :

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

17
Süreleri naramak zorunda kalmadan klasörlere çıkmanın bir yolu var mı os.path.dirname n?
Oriol Nieto

9
@OriolNieto Evet, Python 3.4+ sürümünden itibaren kullanabilirsiniz pathlib.Path.parents[levels_up-1]. Daha fazla çözüm için bu soruya bakın
jwalton

23

Python 3.4 veya daha yenisini kullanıyorsanız, birden fazla dizini yukarı taşımanın kolay bir yolu 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
Bu kesinlikle en temiz yöntemdir.
hobbes3

18

Tam olarak bunu istiyorsun:

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

9

Şahsen, fonksiyon yaklaşımı için giderdim

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

current_dirs_parent = get_parent_dir(os.getcwd())

Girişte sondaki eğik çizgi varsa, bu cevabın işe yaramamasına dikkat edin, örn. os.path.dirname('/tmp/lala/')Yine de dön'/tmp/lala'
Fruit

Sondaki eğik çizgi durumu bu cevaba başvurabilir: stackoverflow.com/a/25669963/1074998
Fruit

7

Bence yapılacak en kolay şey dirname () 'ı tekrar kullanmaktır.

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

dosya /Users/hobbes3/Sites/mysite/templates/method.py adresinde ise

Bu, "/ Kullanıcılar / hobbes3 / Siteler / sitem" döndürür


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

Güncelleme:

settings.pySymlinking yoluyla "kopya" yaparsanız, @ forivall'un cevabı daha iyidir:

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

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

Yukarıdaki yöntem 'görecek' wrong.html, @ forivall'ın yöntemi görecekright.html

Simgelerin yokluğunda iki cevap aynıdır.


Bu yaklaşımda bir sorun var mı? Güzel çalışıyor ve güzel görünüyor ama biraz hackish;)
Gricha

Bağlantılarla nasıl başa çıktığı konusunda kabul edilen cevaptan biraz farklıdır. Aksi takdirde aynıdırlar.
Antony Hatchkins

6

Bu, x klasör yukarı gitmek istediğiniz diğer durumlarda yararlı olabilir. Sadece walk_up_folder(path, 6)6 klasör yukarı gitmek için çalıştırın .

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

for _ in xrange(depth)Yerel değişkeni izlemek yerine sadece kullanabilirsiniz .
Zitrax

2

Benim gibi bir paranoyak için bunu tercih ederim

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

8
belki de yerine '/'kullanmalısınızos.sep
djhaskin987

1

Gitmek için nyukarı ... vadede klasörleriup(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

Kullanarak os.pathböyle bir dizin yukarı gidebiliriz

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

ayrıca istediğiniz dizini bulduktan sonra başka bir dosya / dizin yolu ile katılabilirsiniz

other_image_path = os.path.join(one_directory_up_path, 'other.jpg')
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.