jwalton
jwalton

Reputation: 5686

How to move up n directories in Pythonic way?

I'm looking for a pythonic way to move up n directories from a given directory.

Let's say we have the example path /data/python_env/lib/python3.6/site-packages/matplotlib/mpl-data. If we were to move up n=2 directories we should end up at /data/python_env/lib/python3.6/site-packages.

The following works to move up n directories:

up_n = lambda path, n: '/'.join(path.split('/')[:-n])

However, it's not very readable and fails for paths on windows machines. In essence, it doesn't feel a very pythonic solution.

Is there a better, more pythonic solution, maybe using the os module?

Upvotes: 10

Views: 6603

Answers (5)

martineau
martineau

Reputation: 123541

For Python 3.4+, pathlib is probably the best choice.

That said, here's something that will also work in older versions (including Python 2.x):

import os

def up_n(path, n):
    components = os.path.normpath(path).split(os.sep)
    return os.sep.join(components[:-n])

if __name__ == '__main__':
    path = '/data/python_env/lib/python3.6/site-packages/matplotlib/mpl-data'
    result = up_n(path, 2)
    print(result)  # -> \data\python_env\lib\python3.6\site-packages

Upvotes: 2

Andrew F
Andrew F

Reputation: 2950

One solution to this could take advantage of the shorthand that .. is the parent directory. So, using pathlib you could write

from pathlib import Path
up_n = lambda orig, n: Path(orig).joinpath('/'.join(['..']*n))

Upvotes: 2

adrtam
adrtam

Reputation: 7241

You can use python os.path module for this:

>>> p = '/data/python_env/lib/python3.6/site-packages/matplotlib/mpl-data'
>>> os.path.normpath(os.path.join(p, "..", ".."))
'/data/python_env/lib/python3.6/site-packages'

Or generically for n,

os.path.normpath(os.path.join(*([p]+[".."]*n)))

This way, you don't care it is Windows \ or UNIX / to be used. Python should handle this well. And, you got a one-liner.

Upvotes: 4

Thierry Lathuille
Thierry Lathuille

Reputation: 24289

You can use the pathlib module of the standard library:

from pathlib import Path

path = Path('/data/python_env/lib/python3.6/site-packages/matplotlib/mpl-data')

levels_up = 2
print(path.parents[levels_up-1])
# /data/python_env/lib/python3.6/site-packages

Upvotes: 20

Jean-François Fabre
Jean-François Fabre

Reputation: 140287

how about iterating with os.path.dirname:

import os

s = "/data/python_env/lib/python3.6/site-packages/matplotlib/mpl-data"
for _ in range(2):
    s = os.path.dirname(s)

print(s)

prints:

/data/python_env/lib/python3.6/site-packages

Upvotes: 10

Related Questions