Comment obtenir l'emplacement du répertoire parent

131

ce code est récupéré les templates / blog1 / page.html dans b.py:

path = os.path.join(os.path.dirname(__file__), os.path.join('templates', 'blog1/page.html'))

mais je veux obtenir l'emplacement du répertoire parent:

aParent
   |--a
   |  |---b.py
   |      |---templates
   |              |--------blog1
   |                         |-------page.html
   |--templates
          |--------blog1
                     |-------page.html

et comment obtenir l'emplacement aParent

Merci

actualisé:

c'est juste:

dirname=os.path.dirname
path = os.path.join(dirname(dirname(__file__)), os.path.join('templates', 'blog1/page.html'))

ou

path = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
zjm1126
la source
2
Alors tu veux obtenir blog1ou a? Et où se trouve votre fichier actuel?
Felix Kling
comprenez-vous ce que fait votre code?
SilentGhost
1
oui, il récupère les templates / blog1 / page.html
zjm1126
os.path.join('templates', 'blog1/page.html')me semble étrange. Vous mélangez les choses. Soit os.path.join('templates', 'blog1', 'page.html')ou 'templates/blog1/page.html'. Et beaucoup plus facile serait os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))alors
Felix Kling
1
@zjm: non, vous n'obtenez cette page. Ce n'est pas une boîte noire que vous pouvez simplement utiliser pour obtenir le fichier modèle. Il effectue une série de petites étapes triviales, et si vous pouviez les comprendre, vous n'auriez pas cette question.
SilentGhost

Réponses:

173

Vous pouvez appliquer dirname à plusieurs reprises pour monter plus haut: dirname(dirname(file)). Cependant, cela ne peut aller que jusqu'au package racine. Si cela est un problème, utilisez os.path.abspath: dirname(dirname(abspath(file))).

Marcelo Cantos
la source
37
Je sais que l'OP est au courant dirname. Il n'est pas évident pour tout le monde que l'application de dirname à un répertoire donne le répertoire parent.
Marcelo Cantos
4
dirnamene retourne PAS toujours le répertoire parent; twitter.com/#!/ActiveState/status/671049326788608
Sridhar Ratnakumar
2
@Sridhar: Cela dépend de votre point de vue; Je considère qu'un chemin se terminant /par ne représente pas l'entrée du répertoire feuille elle-même, mais son contenu, c'est pourquoi, par exemple, mv xxx yyy/échoue si ce yyyn'est pas un répertoire préexistant. En tout cas, même si nous prenons votre argument pour acquis, il n’est pas pertinent dans le contexte de ma réponse. Ni fileni le résultat de dirnamene se terminera jamais par un /.
Marcelo Cantos
1
Correction mineure: dirnamepeut revenir '/', ce qui se termine clairement par un /. C'est la seule exception, AFAIK.
Marcelo Cantos
55

os.path.abspathne valide rien, donc si nous ajoutons déjà des chaînes, __file__il n'est pas nécessaire de s'embêter avec dirnameou de rejoindre ou de tout cela. Traitez simplement __file__comme un répertoire et commencez à grimper:

# climb to __file__'s parent's parent:
os.path.abspath(__file__ + "/../../")

C'est beaucoup moins compliqué os.path.abspath(os.path.join(os.path.dirname(__file__),".."))et à peu près aussi gérable que dirname(dirname(__file__)). Grimper sur plus de deux niveaux commence à devenir ridicule.

Mais, puisque nous savons combien de niveaux monter, nous pourrions nettoyer cela avec une petite fonction simple:

uppath = lambda _path, n: os.sep.join(_path.split(os.sep)[:-n])

# __file__ = "/aParent/templates/blog1/page.html"
>>> uppath(__file__, 1)
'/aParent/templates/blog1'
>>> uppath(__file__, 2)
'/aParent/templates'
>>> uppath(__file__, 3)
'/aParent'
joemaller
la source
2
C'est bien, mais ce serait aussi cool si la bibliothèque standard ajoutait une fonction pratique qui accomplissait cela ... je ne veux pas venir à SO chaque fois que j'ai besoin de cette fonction
gradi3nt
4
Serait os.path.abspath(os.path.join(__file__, "..", "..")plus portable?
slowD
40

Utilisez le chemin relatif avec le pathlibmodule dans Python 3.4+:

from pathlib import Path

Path(__file__).parent

Vous pouvez utiliser plusieurs appels à parentpour aller plus loin dans le chemin:

Path(__file__).parent.parent

Au lieu de spécifier parentdeux fois, vous pouvez utiliser:

Path(__file__).parents[1]
Gavriel Cohen
la source
2
Si vous avez besoin du chemin sous forme de chaîne parce que vous souhaitez le modifier, vous pouvez simplement utiliser str(Path(__file__).parent).
Philipp
12
os.path.dirname(os.path.abspath(__file__))

Devrait vous donner le chemin vers a.

Mais si b.pyle fichier est actuellement exécuté, vous pouvez obtenir la même chose en faisant simplement

os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))
Félix Kling
la source
1
o, je sais, vous avez raison, et je veux obtenir le dossier parent de a. comment l'obtenir
zjm1126
@ zjm1126: Voir la réponse de Marcelo Cantos. Appliquer dirname()deux fois. Tout ce dont vous avez besoin maintenant devrait être sur ce site.
Felix Kling
9

os.pardirest un meilleur moyen ../et plus lisible.

import os
print os.path.abspath(os.path.join(given_path, os.pardir))  

Cela retournera le chemin parent du chemin donné

Sun Liwen
la source
5

Un moyen simple peut être:

import os
current_dir =  os.path.abspath(os.path.dirname(__file__))
parent_dir = os.path.abspath(current_dir + "/../")
print parent_dir
Muneeb Ali
la source
3

Peut-être joindre deux ..dossiers, pour obtenir le parent du dossier parent?

path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),"..",".."))
TU
la source
3

Utilisez ce qui suit pour passer au dossier précédent:

os.chdir(os.pardir)

Si vous avez besoin de plusieurs sauts, une bonne et simple solution sera d'utiliser un simple décorateur dans ce cas.

Marco smdm
la source
1

Voici une autre solution relativement simple qui:

  • n'utilise pas dirname()(ce qui ne fonctionne pas comme prévu sur des arguments d'un niveau comme "file.txt" ou des parents relatifs comme "..")
  • n'utilise pas abspath()(évitant toute hypothèse sur le répertoire de travail courant) mais préserve à la place le caractère relatif des chemins

il utilise juste normpathet join:

def parent(p):
    return os.path.normpath(os.path.join(p, os.path.pardir))

# Example:
for p in ['foo', 'foo/bar/baz', 'with/trailing/slash/', 
        'dir/file.txt', '../up/', '/abs/path']:
    print parent(p)

Résultat:

.
foo/bar
with/trailing
dir
..
/abs
Stefaan
la source
0

Je pense que c'est mieux de l'utiliser:

os.path.realpath(__file__).rsplit('/', X)[0]


In [1]: __file__ = "/aParent/templates/blog1/page.html"

In [2]: os.path.realpath(__file__).rsplit('/', 3)[0]
Out[3]: '/aParent'

In [4]: __file__ = "/aParent/templates/blog1/page.html"

In [5]: os.path.realpath(__file__).rsplit('/', 1)[0]
Out[6]: '/aParent/templates/blog1'

In [7]: os.path.realpath(__file__).rsplit('/', 2)[0]
Out[8]: '/aParent/templates'

In [9]: os.path.realpath(__file__).rsplit('/', 3)[0]
Out[10]: '/aParent'
Dongweiming
la source
Pas tout à fait, cela dépend du système d'exploitation (ne fonctionnera pas sous Windows). De plus, il ne permet pas d'utiliser des chemins relatifs.
kgadek
C'est une solution terrible. Ne fonctionnera pas pour tous les systèmes d'exploitation
web.learner
0

J'ai essayé:

import os
os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))), os.pardir))
gogasca
la source