Cómo obtener la ubicación del directorio principal


131

este código es obtener las plantillas / blog1 / page.html en b.py:

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

pero quiero obtener la ubicación del directorio principal:

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

y cómo obtener la ubicación de un padre

Gracias

actualizado:

esto es correcto:

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

o

path = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))

2
¿Entonces quieres blog1o a? ¿Y dónde se encuentra su archivo actual?
Felix Kling

¿Entiendes lo que está haciendo tu código?
SilentGhost

1
sí, obtiene las plantillas / blog1 / page.html
zjm1126

os.path.join('templates', 'blog1/page.html')me parece extraño Estás mezclando cosas. Ya sea os.path.join('templates', 'blog1', 'page.html')o 'templates/blog1/page.html'. Y mucho más fácil sería os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))entonces
Felix Kling

1
@zjm: no, no obtienes esa página. No es una caja negra que podría usar para obtener el archivo de plantilla. Realiza una serie de pequeños pasos triviales, y si pudiera entenderlos, no tendría esta pregunta.
SilentGhost

Respuestas:


173

Puede aplicar nombredir varias veces para subir más alto: dirname(dirname(file)). Sin embargo, esto solo puede llegar hasta el paquete raíz. Si esto es un problema, utilice os.path.abspath: dirname(dirname(abspath(file))).


37
Sé que el OP lo sabe dirname. No es obvio para todos que aplicar dirname a un directorio produce el directorio padre.
Marcelo Cantos

44
dirnameno no siempre volver al directorio padre; twitter.com/#!/ActiveState/status/671049326788608
Sridhar Ratnakumar

2
@Sridhar: Eso depende de tu perspectiva; Considero que una ruta que termina en /no representa la entrada del directorio hoja en sí, sino su contenido, por lo que, por ejemplo, mv xxx yyy/falla si yyyno es un directorio preexistente. En cualquier caso, incluso si tomamos su punto como dado, es irrelevante en el contexto de mi respuesta. Ni fileel resultado de dirnamenunca terminará en a /.
Marcelo Cantos

1
Corrección menor: dirnamepuede regresar '/', lo que claramente termina en a /. Esa es la única excepción, AFAIK.
Marcelo Cantos

55

os.path.abspathno valida nada, así que si ya estamos agregando cadenas __file__no hay necesidad de molestarse dirnameo unirse o nada de eso. Simplemente trátelo __file__como un directorio y comience a escalar:

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

Eso es mucho menos complicado os.path.abspath(os.path.join(os.path.dirname(__file__),".."))y casi tan manejable como dirname(dirname(__file__)). Subir más de dos niveles comienza a ser ridículo.

Pero, dado que sabemos cuántos niveles subir, podríamos limpiar esto con una pequeña función 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'

2
Esto es bueno, pero también estaría bien si la biblioteca estándar añade una función de conveniencia que logró esto ... no quiero ir a por lo que cada vez que necesito esta func
gradi3nt

44
¿ os.path.abspath(os.path.join(__file__, "..", "..")Sería más portátil?
slowD

40

Use la ruta relativa con el pathlibmódulo en Python 3.4+:

from pathlib import Path

Path(__file__).parent

Puede usar varias llamadas parentpara ir más lejos en el camino:

Path(__file__).parent.parent

Como alternativa a especificar parentdos veces, puede usar:

Path(__file__).parents[1]

2
Si necesita la ruta como una cadena porque desea modificarla, simplemente puede usarla str(Path(__file__).parent).
Philipp

12
os.path.dirname(os.path.abspath(__file__))

Debería darte el camino hacia a.

Pero si b.pyes el archivo que se está ejecutando actualmente, entonces puede lograr lo mismo simplemente haciendo

os.path.abspath(os.path.join('templates', 'blog1', 'page.html'))

1
o, lo sé, tienes razón y quiero obtener la carpeta principal de a. cómo conseguirlo
zjm1126

@ zjm1126: Ver la respuesta de Marcelo Cantos. Aplicar dirname()dos veces Todo lo que necesita ahora debe estar en este sitio.
Felix Kling

9

os.pardirEs una mejor manera ../y más legible.

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

Esto devolverá la ruta principal de la ruta dada


5

Una forma simple puede ser:

import os
current_dir =  os.path.abspath(os.path.dirname(__file__))
parent_dir = os.path.abspath(current_dir + "/../")
print parent_dir

3

Se puede unir dos ..carpetas, para obtener el padre de la carpeta principal?

path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),"..",".."))

3

Use lo siguiente para saltar a la carpeta anterior:

os.chdir(os.pardir)

Si necesita varios saltos, una solución buena y fácil será usar un decorador simple en este caso.


1

Aquí hay otra solución relativamente simple que:

  • no usa dirname()(que no funciona como se esperaba en argumentos de un nivel como "file.txt" o padres relativos como "..")
  • no usa abspath()(evitando cualquier suposición sobre el directorio de trabajo actual) sino que conserva el carácter relativo de las rutas

solo usa normpathy 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)

Resultado:

.
foo/bar
with/trailing
dir
..
/abs

0

Creo que usar esto es mejor:

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'

No del todo, depende del sistema operativo (no funcionará en Windows). Además, no permite utilizar rutas relativas.
kgadek

Esa es una solución terrible. No funcionará para todos los sistemas operativos
web.learner

0

Lo intenté:

import os
os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))), os.pardir))
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.