Wie gehe ich mit Pythons os.path in ein Verzeichnis?

224

Ich habe kürzlich Django von v1.3.1 auf v1.4 aktualisiert.

In meinem alten settings.pyhabe ich

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

Dies wird darauf hinweisen /Users/hobbes3/Sites/mysite/templates, aber da Django v1.4 den Projektordner auf die gleiche Ebene wie die App-Ordner verschoben hat , befindet sich meine settings.pyDatei jetzt in /Users/hobbes3/Sites/mysite/mysite/statt /Users/hobbes3/Sites/mysite/.

Eigentlich ist meine Frage jetzt zweifach:

  1. Wie verwende ich os.pathin einem Verzeichnis einer Ebene suchen oben aus __file__. Mit anderen Worten, ich möchte /Users/hobbes3/Sites/mysite/mysite/settings.pyfinden /Users/hobbes3/Sites/mysite/templatesmit relativen Pfaden.
  2. Sollte ich das sein halten templateOrdner (die Quer App - Vorlagen hat, wie admin, registrationetc.) auf /User/hobbes3/Sites/mysiteProjektebene oder auf /User/hobbes3/Sites/mysite/mysite?
hobbes3
quelle
Cant Sie verwenden nur oszu cdzu ../mysite? Oder was auch immer Sie wollen
Prelic
@ Prelic Hmm? Ich verstehe nicht. Ich versuche zu vermeiden, den Pfad fest zu codieren, da ich ihn settings.pyauf mehreren Servern verwende. Der einzige Unterschied könnten die Datenbankanmeldeinformationen sein. Ich habe die os.pathDokumentation gelesen , aber keinen Befehl gefunden, mit dem Sie ein Verzeichnis aufrufen können. Wie cd ...
hobbes3
2
@ hobbes3 können Sie nur os.path.join( os.path.dirname( __file__ ), '..' ) ..bedeutet , das Verzeichnis über das ganze Dateisystem, nicht nur , wenn übergeben cd.
Michael Berkowski
3
@ Michael, es ist wahrscheinlich besser zu verwendenos.path.join( os.path.dirname ( __file__), os.path.pardir)
mgilson

Antworten:

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

Wie weit der Vorlagenordner gehen soll, weiß ich nicht, da Django 1.4 gerade herausgekommen ist und ich es mir noch nicht angesehen habe. Sie sollten wahrscheinlich eine andere Frage zu SE stellen, um dieses Problem zu lösen.

Sie können normpathden Pfad auch verwenden, anstatt ihn zu bereinigen abspath. In dieser Situation erwartet Django jedoch eher einen absoluten als einen relativen Pfad.

Verwenden Sie os.pardiraus Gründen der plattformübergreifenden Kompatibilität anstelle von '..'.

forivall
quelle
4
Ist es eine schlechte Idee ..oder etwas? Warum bekommt diese Antwort weniger Stimmen?
hobbes3
1
Ich weiß nicht, warum es weniger Stimmen bekommt, aber es ist das, was ich immer benutzt habe. Es ist sogar im Beispiel für definiert normpath. Außerdem werden Symlinks ordnungsgemäß durchlaufen.
Forivall
1
Mit abspath wird es nur ein bisschen aufgeräumt. Wenn es nicht vorhanden ist, /Users/hobbes3/Sites/mysite/mysite/../templateslautet die eigentliche Zeichenfolge für den Pfadnamen , was vollkommen in Ordnung ist, aber nur ein wenig überladener. Es stellt auch sicher, dass Djangos Erinnerung an die Verwendung absoluter Pfade eingehalten wird. Wenn Sie sich in einer anderen Situation befinden, in der ein relativer Pfad verwendet wird, sollten Sie stattdessen den Normpfad verwenden, um Ihre Pfade zu vereinfachen.
Forivall
2
Diese Frage wurde nur bezüglich der Migration der Ordnerstruktur für die neue Version von Django gestellt . Sie sollten sich also wahrscheinlich darum kümmern, um Ihr zweites Problem zu lösen.
Forivall
1
@Zitrax Kennen Sie Plattformen, auf denen dies anders wäre, oder ist es nur für die zukünftige Sicherheit da? (Ich wusste es eigentlich nicht, bin os.pardirden osDokumenten nie auf den Grund
gegangen
98

Um den Ordner einer Datei zu erhalten, verwenden Sie einfach:

os.path.dirname(path) 

Um einen Ordner zu erstellen, verwenden Sie ihn einfach os.path.dirnameerneut

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

Vielleicht möchten Sie überprüfen, ob __file__es sich um einen Symlink handelt:

if os.path.islink(__file__): path = os.readlink (__file__)
locojay
quelle
17
Gibt es eine Möglichkeit, nOrdner aufzurufen, ohne die os.path.dirname nZeiten anrufen zu müssen ?
Oriol Nieto
9
@OriolNieto Ja, ab Version Python 3.4+ können Sie verwenden pathlib.Path.parents[levels_up-1]. Siehe diese Frage für weitere Lösungen
Jwalton
23

Wenn Sie Python 3.4 oder höher verwenden, können Sie bequem mehrere Verzeichnisse nach oben verschieben 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
quelle
2
Dies ist definitiv die sauberste Methode.
hobbes3
18

Sie wollen genau das:

BASE_DIR = os.path.join( os.path.dirname( __file__ ), '..' )
Alan Viars
quelle
9

Persönlich würde ich mich für den Funktionsansatz entscheiden

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

current_dirs_parent = get_parent_dir(os.getcwd())
Lord Sumner
quelle
Seien Sie vorsichtig, diese Antwort funktioniert nicht, wenn die Eingabe einen abschließenden Schrägstrich enthält, z. B. os.path.dirname('/tmp/lala/')immer noch zurückkehren'/tmp/lala'
Fruit
Der nachfolgende
Fruit
7

Ich denke, das Einfachste ist, dirname () wiederzuverwenden, damit du anrufen kannst

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

Wenn sich Ihre Datei unter /Users/hobbes3/Sites/mysite/templates/method.py befindet

Dies gibt "/ Users / hobbes3 / Sites / mysite" zurück.

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

Aktualisieren:

Wenn Sie settings.pydurch Symlinking "kopieren" , ist die Antwort von @ forivall besser:

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

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

Die obige Methode wird "sehen", wrong.htmlwährend die Methode von @ forivall sehen wirdright.html

In Abwesenheit von Symlinks sind die beiden Antworten identisch.

Antony Hatchkins
quelle
Stimmt etwas mit diesem Ansatz nicht? Es funktioniert gut und sieht gut aus, aber ein bisschen hackisch;)
Gricha
Es unterscheidet sich geringfügig von der akzeptierten Antwort im Umgang mit den Links. Sie sind ansonsten identisch.
Antony Hatchkins
6

Dies kann in anderen Fällen nützlich sein, in denen Sie x Ordner nach oben verschieben möchten. Führen Sie einfach walk_up_folder(path, 6)6 Ordner aus.

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
quelle
Könnte nur verwendet werden, for _ in xrange(depth)anstatt die lokale Variable zu verfolgen.
Zitrax
2

Für einen Paranoiden wie mich würde ich diesen vorziehen

TEMPLATE_DIRS = (
    __file__.rsplit('/', 2)[0] + '/templates',
)
Hasserh
quelle
8
Vielleicht '/'sollten Sie stattdessenos.sep
djhaskin987
1

Gehen nOrdner auf ... runup(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
quelle
0

Natürlich: einfach benutzen os.chdir(..).

Das Shwarma
quelle
0

Mit der Verwendung können os.pathwir ein Verzeichnis so nach oben gehen

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

Auch nachdem Sie das gewünschte Verzeichnis gefunden haben, können Sie sich mit einem anderen Datei- / Verzeichnispfad verbinden

other_image_path = os.path.join(one_directory_up_path, 'other.jpg')
abdullahselek
quelle