Usando os.path de Python, ¿cómo subo un directorio?

5 minutos de lectura

avatar de usuario
hobbes3

Recientemente actualicé Django de v1.3.1 a v1.4.

en mi viejo settings.py tengo

TEMPLATE_DIRS = (
    os.path.join(os.path.dirname( __file__ ), 'templates').replace('\\', "https://stackoverflow.com/"),
    # 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.
)

Esto apuntará a /Users/hobbes3/Sites/mysite/templatespero porque Django v1.4 movió la carpeta del proyecto al mismo nivel que las carpetas de la aplicaciónmi settings.py el archivo está ahora en /Users/hobbes3/Sites/mysite/mysite/ en vez de /Users/hobbes3/Sites/mysite/.

Así que en realidad mi pregunta ahora es doble:

  1. ¿Cómo uso os.path para buscar en un directorio un nivel por encima de __file__. En otras palabras, quiero /Users/hobbes3/Sites/mysite/mysite/settings.py encontrar /Users/hobbes3/Sites/mysite/templates utilizando rutas relativas.
  2. ¿Debería mantener el template carpeta (que tiene plantillas de aplicaciones cruzadas, como admin, registrationetc.) en el proyecto /User/hobbes3/Sites/mysite nivel o en /User/hobbes3/Sites/mysite/mysite?

  • ¿No puedes simplemente usar os a cd a ../mysite? O el comando que quieras

    – preliquia

    24 de marzo de 2012 a las 23:44


  • @prelic Hmmm? No entiendo. Estoy tratando de evitar codificar la ruta, porque uso el mismo settings.py en múltiples servidores. La única diferencia podría ser las credenciales de la base de datos. estaba leyendo el os.path documentación pero no pude encontrar un comando que te permita subir un directorio. Me gusta cd ...

    – hobbes3

    24 de marzo de 2012 a las 23:46


  • @hobbes3 Puedes simplemente os.path.join( os.path.dirname( __file__ ), '..' ) .. medio el directorio de arriba en todo el sistema de archivos, no solo cuando se pasa a cd.

    –Michael Berkowski

    24 de marzo de 2012 a las 23:48


  • @Michael, probablemente sea mejor usar os.path.join( os.path.dirname ( __file__), os.path.pardir)

    – mgilson

    24/03/2012 a las 23:50


avatar de usuario
Forivall

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

En cuanto a dónde debería ir la carpeta de plantillas, no lo sé, ya que acaba de salir Django 1.4 y aún no lo he mirado. Probablemente debería hacer otra pregunta sobre SE para resolver ese problema.

También puedes usar normpath para limpiar el camino, en lugar de abspath. Sin embargo, en esta situación, Django espera una ruta absoluta en lugar de una ruta relativa.

Para compatibilidad multiplataforma, utilice os.pardir en vez de '..'.

  • ¿Es una mala idea usar .. ¿o algo? ¿Por qué esta respuesta recibe menos votos?

    – hobbes3

    25 de marzo de 2012 a las 0:01


  • No sé por qué está recibiendo menos votos, pero es lo que siempre he usado. Incluso se define en el ejemplo para normpath. Además, atravesará los enlaces simbólicos correctamente.

    – Forivall

    25 de marzo de 2012 a las 0:06


  • Usar abspath solo lo limpiará un poco. Si no está allí, la cadena real para el nombre de la ruta será /Users/hobbes3/Sites/mysite/mysite/../templates, que está perfectamente bien, pero un poco más desordenado. También asegura que se obedezca el recordatorio de Django para usar rutas absolutas. Si se encuentra en una situación diferente que usa una ruta relativa, debe usar normpath para simplificar sus rutas.

    – Forivall

    25 de marzo de 2012 a las 1:29


  • Esta pregunta se acaba de hacer con respecto a la migración de la estructura de carpetas para la nueva versión de Django, por lo que probablemente debería buscarla para resolver su segundo problema.

    – Forivall

    25 de marzo de 2012 a las 2:16

  • @Zitrax ¿Conoce alguna plataforma en la que esto sería diferente, o solo está ahí por seguridad en el futuro? (En realidad no sabía sobre os.pardiren realidad nunca llegó al fondo de la os documentos)

    – Forivall

    20 de febrero de 2013 a las 19:54

avatar de usuario
jassinm

Para obtener la carpeta de un archivo, simplemente use:

os.path.dirname(path) 

Para obtener una carpeta solo use os.path.dirname otra vez

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

Es posible que desee comprobar si __file__ es un enlace simbólico:

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

  • ¿Hay alguna manera de subir? n carpetas sin tener que llamar os.path.dirname n ¿veces?

    –Oriol Nieto

    20 de junio de 2015 a las 18:55

  • @OriolNieto Sí, a partir de la versión Python 3.4+ se puede usar pathlib.Path.parents[levels_up-1]. Ver esta pregunta para más soluciones

    – jwalton

    4 de abril de 2019 a las 15:22

Si está utilizando Python 3.4 o posterior, una forma conveniente de subir varios directorios es 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])  # "."

  • Este es definitivamente el método más limpio.

    – hobbes3

    17 de noviembre de 2019 a las 2:33

avatar de usuario
Señor Sumner

Personalmente, optaría por el enfoque de función.

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

current_dirs_parent = get_parent_dir(os.getcwd())

Creo que lo más fácil de hacer es simplemente reutilizar dirname() Para que pueda llamar

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

si su archivo está en /Users/hobbes3/Sites/mysite/templates/method.py

Esto devolverá “/Usuarios/hobbes3/Sitios/misitio”

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

Actualizar:

Si por casualidad “copias” settings.py a través de enlaces simbólicos, la respuesta de @ forivall es mejor:

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

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

El método anterior ‘verá’ wrong.html mientras que el método de @forivall verá right.html

En ausencia de enlaces simbólicos, las dos respuestas son idénticas.

avatar de usuario
Marcus Krautwurst

Esto podría ser útil para otros casos en los que desee subir x carpetas. Solo corre walk_up_folder(path, 6) para subir 6 carpetas.

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

  • Podría usar for _ in xrange(depth) en lugar de realizar un seguimiento de la variable local.

    – Zitrax

    23 de octubre de 2018 a las 8:24

¿Ha sido útil esta solución?