os.path.join for getting up level paths

Question:

Consider you have the following code:
os.path.abspath(os.path.join('../../', __file__))

I am quite puzzled because currently, it is returning me the same path such in __file__ path.

Any idea why I don’t get two levels up of the __file__ path?

Asked By: JavaSa

||

Answers:

From the documentation (emphasis mine):

os.path.join(path, *paths)

Join one or more path components
intelligently. The return value is the concatenation of path and any
members of *paths with exactly one directory separator (os.sep)
following each non-empty part except the last, meaning that the result
will only end in a separator if the last part is empty. If a component
is an absolute path, all previous components are thrown away and
joining continues from the absolute path component
.

__file__ is an absolute path, so join ignores the preceding ../../.

Answered By: chepner

__file__ is an absolute file path and so the join attempts something like the following:

os.path.join('../../', '/path/to/file')

Since the second argument is already an absolute path, all previous ones are ineffective.

Also note that __file__ contains the file name itself so if you want to go two directories up you’d need to split that off. The easiest solution is to use pathlib.Path:

Path(__file__).parents[2]

If you want to go n levels up you can use Path(__file__).parents[n].

Answered By: a_guest

After some more trial and error I think I found the best solution:

os.path.abspath(os.path.join(__file__, '../../'))
Answered By: JavaSa

This worked for me. A few years later. Looks to me like abspath will make sure ../ work as it should in a path instead of just a normal string. Absolute genius.

Answered By: cgmikeg
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.