问题
I find myself needing to get a parent directory of a python file in a source tree that is multiple directories up with some regularity. Having to call dirname many times is clunky.
I looked around and was surprised to not find posts on this.
The general scenario is:
import os.path as op
third_degree_parent = op.dirname(op.dirname(op.dirname(op.realpath(__file__))))
Is there a more idiomatic way to do this that doesn't require nested dirname calls?
回答1:
Normalize a relative path; os.pardir is the parent directory, repeat it as many times as needed. It is available via os.path.pardir
too:
import os.path as op
op.abspath(op.join(__file__, op.pardir, op.pardir, op.pardir))
回答2:
def updir(d, n):
"""Given path d, go up n dirs from d and return that path"""
ret_val = d
for _ in range(n):
ret_val = os.path.dirname(ret_val)
return ret_val
Given a directory d = '/path/to/some/long/dir'
you can use the above function to go up as many levels as you want. For example:
updir(d,0)
'/path/to/some/long/dir'
updir(d,1)
'/path/to/some/long'
updir(d,2)
'/path/to/some'
updir(d,3)
'/path/to'
updir(d,4)
'/path'
回答3:
Since it has not been demonstrated yet, here is an answer using a recursive function.
Function
import os
def parent(path, level = 0):
parent_path = os.path.dirname(path)
if level == 0:
return parent_path
return parent(parent_path, level - 1)
Explaination
- get the dirname of a path that is input
- if the level is not 0, function calls itself, causing it to get the dirname of the dirname
- process repeats recursively until level has reached 0
Example
>>> parent('/my/long/path/name/with/a/file.txt')
'/my/long/path/name/with/a'
>>> parent('/my/long/path/name/with/a/file.txt', 0)
'/my/long/path/name/with/a'
>>> parent('/my/long/path/name/with/a/file.txt', 4)
'/my/long'
回答4:
Someone else added an answer in 2018, 4 years later, so why not add mine. The other answers are either long or become long if a larger number of parents are required. Let's say you need 7 parents. This is what I do
os.path.abspath(__file__ + 8 * '/..')
Note the extra (8=7+1) to remove 7 parents as well as the file name. No need for os.path.pardir
as abspath
understands /..
universally and will do the right thing. Also has the advantage that the number of parents can be dynamic, determined at run-time.
In comparison, the equivalent using the accepted answer (longer and less obvious):
import os.path as op
op.abspath(op.join(__file__, op.pardir, op.pardir, op.pardir, op.pardir, op.pardir, op.pardir, op.pardir))
回答5:
I will extend the accepted answer with N
import os.path as op
op.abspath(op.join(__file__, \*N\*[op.pardir]))
来源:https://stackoverflow.com/questions/25815055/python-idiom-to-get-same-result-as-calling-os-path-dirname-multiple-times