python: obtenga el directorio dos niveles arriba

86

Ok ... No sé dónde xestá el módulo , pero sé que necesito obtener la ruta al directorio dos niveles más arriba.

Entonces, ¿hay una forma más elegante de hacer:

import os
two_up = os.path.dirname(os.path.dirname(__file__))

¡Las soluciones para Python 2 y 3 son bienvenidas!

jramm
fuente
1
Creo que tu solución está perfectamente bien. Una pathlibsolución es un poco más agradable y legible, pero no se incluye con Python 2.7. Yo diría que se quede con lo que tiene, tal vez agregue un comentario.
jme
Quizás valga la pena agregar la pip install pathlib2opción para mantener la cordura en 2.7.
jonathan

Respuestas:

104

Puede utilizar pathlib. Desafortunadamente, esto solo está disponible en stdlib para Python 3.4. Si tiene una versión anterior, tendrá que instalar una copia de PyPI aquí . Esto debería ser fácil de usar pip.

from pathlib import Path

p = Path(__file__).parents[1]

print(p)
# /absolute/path/to/two/levels/up

Esto usa la parentssecuencia que proporciona acceso a los directorios principales y elige el segundo.

Tenga pen cuenta que en este caso habrá alguna forma de Pathobjeto, con sus propios métodos. Si necesita las rutas como una cadena, puede llamarlas str.

Ffisegydd
fuente
Esa es una buena respuesta, gracias y genial para py3. Para py2 es posible que no sea mejor que mi intento inicial, ya que crea una dependencia adicional
jramm
16
Esta no debería ser la respuesta aceptada ya que la Pathclase parentsdepende de la ubicación de ejecución. Si ejecuta su __file__desde su directorio actual, la Pathclase no tendrá padres. Se debe aceptar la respuesta de @ Sebi2020 o se debe utilizar su método original. Creo que tu método original es más legible.
Red-Tune-84
1
Puede que p = Path(os.path.abspath(__file__)).parents[1]
tengas
4
@AdamRaudonis En lugar de os.path.abspath, también puede usarPath(__file__).resolve().parents[1]
Tulio Casagrande
7
Como mencionó @Kazanz, esta solución no funciona cuando se ejecuta desde otras rutas. La mejor solución es: p = Path(__file__).resolve().parents[1]. También lo agregué como respuesta.
pythinker
46

Muy fácil:

Esto es lo que quieres:

import os.path as path

two_up =  path.abspath(path.join(__file__ ,"../.."))
Sebi2020
fuente
8
Y quizás use en os.pardirlugar de ...
jme
¿sys.argv [0] no devuelve el módulo que fue ejecutado por python.exe? Así que esto no funcionaría necesariamente si el módulo que me interesa fuera importado de algún otro paquete ... ¿estoy aquí?
jramm
Si desea usarlo en un módulo, use __file__.
Sebi2020
1
@jme, ¿conoce un sistema operativo en el que obtiene el directorio principal con otra cadena que ".." ???
Sebi2020
1
@ Sebi2020 Sí, en particular el antiguo Mac OS. Aquí hay una lista: en.wikipedia.org/wiki/Path_(computing)
jme
22

Iba a agregar esto solo para ser tonto, pero también porque muestra a los recién llegados la utilidad potencial de las funciones de aliasing y / o las importaciones.

Habiéndolo escrito, creo que este código es más legible (es decir, menos tiempo para comprender la intención) que las otras respuestas hasta la fecha, y la legibilidad es (generalmente) el rey.

from os.path import dirname as up

two_up = up(up(__file__))

Nota: solo desea hacer este tipo de cosas si su módulo es muy pequeño o cohesivo contextualmente.

andyhasit
fuente
14

La mejor solución (para python> = 3.4) cuando se ejecuta desde cualquier directorio es:

from pathlib import Path
two_up = Path(__file__).resolve().parents[1]
pythinker
fuente
10

Para subir los niveles del directorio 2:

 import os.path as path
 two_up = path.abspath(path.join(os.getcwd(),"../.."))
zerocog
fuente
4

Personalmente, creo que usar el módulo del sistema operativo es el método más fácil, como se describe a continuación. Si sólo va a subir un nivel, reemplace ('../ ..') por ('..').

    import os
    os.chdir('../..')

--Check:
    os.getcwd()
M. Murphy
fuente
1
¿Es aceptable codificar de forma rígida el '/' que habría esperado leer os.chdir (os.join ('..', '..'))
GreenAsJade
2

He descubierto que lo siguiente funciona bien en 2.7.x

import os
two_up = os.path.normpath(os.path.join(__file__,'../'))
Lucidioso
fuente
1

Puede usar esto como una solución genérica:

import os

def getParentDir(path, level=1):
  return os.path.normpath( os.path.join(path, *([".."] * level)) )
Axel Heider
fuente
@JanSila: puede ser más específico, ¿por qué no es pitónico? Para mayor legibilidad, podría tener más comentarios sobre lo que hace, sí, pero al final está utilizando características estándar del lenguaje Python, consulte, por ejemplo, stackoverflow.com/questions/36901
Axel Heider
Es un poco denso, pero no creo que sea demasiado abstracto ni legible. Es solo una versión generalizada de otras respuestas publicadas aquí. Sin embargo, me gustaría una forma de biblioteca estándar de hacer las cosas sin la necesidad de implementar una función.
ryanjdillon
1

Más implementación multiplataforma será:

import pathlib
two_up = (pathlib.Path(__file__) / ".." / "..").resolve()

El uso parentno es compatible con Windows. También es necesario agregar .resolve()a:

Haga que la ruta sea absoluta, resolviendo todos los enlaces simbólicos en el camino y también normalizándola (por ejemplo, convirtiendo barras en barras invertidas en Windows)

zhukovverde
fuente
2
¿Tiene una fuente para parentno trabajar en Windows? Esto parece haberse solucionado en algún momento desde que escribiste este comentario. Funciona bien para mí usando Python 3.7.2 en Windows 10.
Nathan
Podría empezar a parenttrabajar en Windows 10 con Python 3.6.5. ¿De qué versión de Python estás hablando @Zhukovgeen?
ggulgulia
@ggulgulia creo que fue 3.7
zhukovgreen
0

Suponiendo que desea acceder a la carpeta llamada xzy, dos carpetas en su archivo de Python. Esto funciona para mí e independientemente de la plataforma.

".././xyz"

usuario11770816
fuente
0

(pathlib.Path ('../../')) .resolve ()

Alexis
fuente
Da la ruta relativa al directorio de trabajo, no al módulo
jramm
-1

Todavía no veo una respuesta viable para 2.7 que no requiere la instalación de dependencias adicionales y también comienza desde el directorio del archivo. No es agradable como solución de una sola línea, pero no hay nada de malo en usar las utilidades estándar.

import os

grandparent_dir = os.path.abspath(  # Convert into absolute path string
    os.path.join(  # Current file's grandparent directory
        os.path.join(  # Current file's parent directory
            os.path.dirname(  # Current file's directory
                os.path.abspath(__file__)  # Current file path
            ),
            os.pardir
        ),
        os.pardir
    )
)

print grandparent_dir

Y para demostrar que funciona, aquí empiezo ~/Documents/notessolo para mostrar que el directorio actual no influye en el resultado. Puse el archivo grandpa.pycon ese script en una carpeta llamada "scripts". Se arrastra hasta el directorio de Documentos y luego al directorio de usuario en una Mac.

(testing)AlanSE-OSX:notes AlanSE$ echo ~/Documents/scripts/grandpa.py 
/Users/alancoding/Documents/scripts/grandpa.py
(testing)AlanSE-OSX:notes AlanSE$ python2.7 ~/Documents/scripts/grandpa.py 
/Users/alancoding

Esta es la extrapolación obvia de la respuesta para el directorio principal . Es mejor usar una solución general que una solución menos buena en menos líneas.

AlanSE
fuente
-1

para py 3.4 y versiones posteriores, pathlib

ejemplo:

from pathlib import Path
path = Path("../../data/foo/someting.csv").resolve()
O-9
fuente
Esto da la ruta relativa al directorio de trabajo, no al módulo
jramm