Используя Python os.path, как мне перейти на один каталог?

129

Недавно я обновил Django с версии 1.3.1 до версии 1.4.

В моем старом settings.py у меня есть

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

Это укажет на /Users/hobbes3/Sites/mysite/templates, но поскольку Django v1.4 переместил папку проекта на тот же уровень, что и папки приложений, мой settings.py теперь находится в /Users/hobbes3/Sites/mysite/mysite/ вместо /Users/hobbes3/Sites/mysite/.

Итак, мой вопрос сейчас двоякий:

  • Как использовать os.path для просмотра каталога на одном уровне выше от __file__. Другими словами, я хочу, чтобы /Users/hobbes3/Sites/mysite/mysite/settings.py находил /Users/hobbes3/Sites/mysite/templates, используя относительные пути.
  • Должен ли я хранить папку template (у которой есть шаблоны кросс-приложений, такие как admin, registration и т.д.) на уровне проекта /User/hobbes3/Sites/mysite или в /User/hobbes3/Sites/mysite/mysite?
  • 0
    Cant вы просто используете os с cd - ../mysite cd в ../mysite ? Или любую команду, которую вы хотите
  • 0
    @ прелишко Хмм? Я не понимаю Я пытаюсь избежать жесткого кодирования пути, потому что я использую один и тот же settings.py на нескольких серверах. Единственной разницей могут быть учетные данные базы данных. Я читал документацию os.path но не смог найти команду, которая позволила бы вам перейти на один каталог. Как cd ..
Показать ещё 2 комментария
Теги:

8 ответов

153
Лучший ответ
os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'templates'))

Насколько папка шаблонов должна идти, я не знаю, так как Django 1.4 только что вышел, и я еще не посмотрел на него. Вероятно, вы должны задать другой вопрос в SE, чтобы решить эту проблему.

Вы также можете использовать normpath для очистки пути, а не abspath. Однако в этой ситуации Django ожидает абсолютный путь, а не относительный путь.

Для совместимости с кросс-платформой используйте os.pardir вместо '..'.

  • 3
    Это плохая идея использовать .. или что-то? Почему этот ответ получает меньше голосов?
  • 1
    Я не знаю, почему он получает меньше голосов, но это то, что я всегда использовал. Это даже определено в примере для normpath . Кроме того, он будет правильно проходить по символическим ссылкам.
Показать ещё 6 комментариев
49

Чтобы получить папку с файлом, просто используйте:

os.path.dirname(path) 

Чтобы получить папку, просто используйте os.path.dirname снова

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

Вы можете проверить, является ли __file__ символической ссылкой:

if os.path.islink(__file__): path = os.readlink (__file__)
  • 15
    Есть ли способ открыть n папок, не os.path.dirname n раз?
12

Вы хотите именно это:

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

Update:

Если вам случится "копировать" settings.py через символическую привязку, лучше ответить на @forivall:

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

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

Метод выше будет "видеть" wrong.html, в то время как метод @forivall увидит right.html

В отсутствии символических ссылок два ответа идентичны.

  • 0
    Что-то не так с этим подходом? Работает хорошо и выглядит красиво, но немного хакерски;)
  • 0
    Он немного отличается от принятого ответа тем, как он работает со ссылками. В противном случае они идентичны.
4

Лично я бы пошел на функциональный подход

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

current_dirs_parent = get_parent_dir(os.getcwd())
  • 0
    Будьте осторожны, этот ответ не работает, если ввод содержит косую черту, например, os.path.dirname('/tmp/lala/') все еще возвращает '/tmp/lala'
  • 0
    Конечный слеш может ссылаться на этот ответ: stackoverflow.com/a/25669963/1074998
3

Это может быть полезно для других случаев, когда вы хотите перейти в x папки вверх. Просто запустите walk_up_folder(path, 6), чтобы перейти в 6 папок.

def walk_up_folder(path, depth=1):
    _cur_depth = 1        
    while _cur_depth < depth:
        path = os.path.dirname(path)
        _cur_depth += 1
    return path   
  • 0
    Можно просто использовать for _ in xrange(depth) вместо отслеживания локальной переменной.
3

Я думаю, что проще всего просто повторить использование dirname() Поэтому вы можете позвонить

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

если файл находится в /Users/hobbes 3/Sites/mysite/templates/method.py

Это вернет "/Users/hobbes3/Sites/mysite"

2

Для такого же параноида, как я, я бы предпочел этот

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

  • 7
    возможно, вместо '/' вы должны использовать os.sep

Ещё вопросы

Сообщество Overcoder
Наверх
Меню