python: get directory two levels up

Question:

Ok…I dont know where module x is, but I know that I need to get the path to the directory two levels up.

So, is there a more elegant way to do:

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

Solutions for both Python 2 and 3 are welcome!

Asked By: jramm

||

Answers:

You can use pathlib. Unfortunately this is only available in the stdlib for Python 3.4. If you have an older version you’ll have to install a copy from PyPI here. This should be easy to do using pip.

from pathlib import Path

p = Path(__file__).parents[1]

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

This uses the parents sequence which provides access to the parent directories and chooses the 2nd one up.

Note that p in this case will be some form of Path object, with their own methods. If you need the paths as string then you can call str on them.

Answered By: Ffisegydd

Very easy:

Here is what you want:

import os.path as path

two_up =  path.abspath(path.join(__file__ ,"../.."))
Answered By: Sebi2020

Personally, I find that using the os module is the easiest method as outlined below. If you are only going up one level, replace (‘../..’) with (‘..’).

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

--Check:
    os.getcwd()
Answered By: user4816510

I don’t yet see a viable answer for 2.7 which doesn’t require installing additional dependencies and also starts from the file’s directory. It’s not nice as a single-line solution, but there’s nothing wrong with using the standard utilities.

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

And to prove it works, here I start out in ~/Documents/notes just so that I show the current directory doesn’t influence outcome. I put the file grandpa.py with that script in a folder called “scripts”. It crawls up to the Documents dir and then to the user dir on a 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

This is the obvious extrapolation of the answer for the parent dir. Better to use a general solution than a less-good solution in fewer lines.

Answered By: AlanSE

I have found that the following works well in 2.7.x

import os
two_up = os.path.normpath(os.path.join(__file__,'../'))
Answered By: Lucidious

You can use this as a generic solution:

import os

def getParentDir(path, level=1):
  return os.path.normpath( os.path.join(path, *([".."] * level)) )
Answered By: Axel Heider

For getting the directory 2 levels up:

 import os.path as path
 curr_dir=Path(os.path.dirname(os.path.abspath(__file__)))
 two_dir_up_=os.fspath(Path(curr_dir.parent.parent).resolve())

I have done the following to go up two and drill down on other dir

 default_config_dir=os.fspath(Path(curr_dir.parent.parent,
                                   'data/config').resolve()) 
Answered By: zerocog

I was going to add this just to be silly, but also because it shows newcomers the potential usefulness of aliasing functions and/or imports.

Having written it, I think this code is more readable (i.e. lower time to grasp intention) than the other answers to date, and readability is (usually) king.

from os.path import dirname as up

two_up = up(up(__file__))

Note: you only want to do this kind of thing if your module is very small, or contextually cohesive.

Answered By: andyhasit

More cross-platform implementation will be:

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

Using parent is not supported on Windows. Also need to add .resolve(), to:

Make the path absolute, resolving all symlinks on the way and also normalizing it (for example turning slashes into backslashes under Windows)

Answered By: zhukovgreen

The best solution (for python >= 3.4) when executing from any directory is:

from pathlib import Path
two_up = Path(__file__).resolve().parents[1]
Answered By: pythinker

Assuming you want to access folder named xzy two folders up your python file. This works for me and platform independent.

“.././xyz”

Answered By: user11770816

(pathlib.Path(‘../../’) ).resolve()

Answered By: Alexis

100% working answer:

os.path.abspath(os.path.join(os.getcwd() ,"../.."))
Answered By: Jason Lim Ji Chen

There is already an accepted answer, but for two levels up I think a chaining approach is arguably more readable:

pathlib.Path(__file__).parent.parent.resolve()
Answered By: tek

Surprisingly it seems no one has yet explored this nice one-liner option:

import os
two_up = os.path.normpath(__file__).rsplit(os.sep, maxsplit=2)[0]

rsplit is interesting since the maxsplit parameter directly represents how many parent folders to move up and it always returns a result in just one pass through the path.

Answered By: glopes

With Pathlib (recommended after Python 3.5, the/a general solution that works not only in file.py files, but also in Jupyter (or other kind of) notebook and Python shell is:

p = Path.cwd().resolve().parents[1]

You only need to substitute (__file__) for cwd() (current working directory).

Indeed it would even work just with:

p = Path().resolve().parents[1]

(and of course with .parent.parent instead of parents[1])

Answered By: Martin