Python: Elegent way to get an iterable of all parents in a path

python pathlib path
python pathlib path to string
python pathlib copy file
pathlib absolute path
pathlib relative path
pathlib list files
python path parent
path python

Working with a path-based resource system, the application needs to find the first working resource that manages a given resource based on paths. I need a succinct, pythonic way to generate the following:

Input:

/house/dogs/ralph/bone

Output:

/house/dogs/ralph/bone
/house/dogs/ralph
/house/dogs
/house

Note: It's okay to use os.path or similar built-ins, but these are not filesystem resources. Output can be anything iterable (list, set, generator, etc.).

Use pathlib. PurePaths offer an abstract interface to path-like objects that have no relationship to the file system. In particular, PurePosixPath is the kind that uses forward slashes (/) as separators:

>>> from pathlib import PurePosixPath
>>> p = PurePosixPath('/house/dogs/ralph/bone')
>>> str(p.parent)
/house/dogs/ralph
>>> str(p.parent.parent)
/house/dogs

You can loop this easily:

p = PurePosixPath(...)
while p != p.root:
    # Do stuff to p
    p = p.parent

A fairly pythonic finishing touch would be to make it a generator:

def receding_path(p):
    p = PurePosixPath(p)
    while p != p.root:
        yield str(p)
        p = p.parent

for item in receding_path('/house/dogs/ralph/bone'):
    # do stuff to each item

Get the path of running file (.py) in Python: __file, Working with a path-based resource system, the application needs to find the first working resource that manages a given resource based on paths. I need a  The sum() function is used to get the sum of all items in an iterable. tuple() The tuple() function is used to create a tuple in Python. Iterable may be a sequence, a container that supports iteration, or an iterator object. type() The type() function is used to get the type of an object. vars

One way would be to split the string on "/" and take successive slices.

in_string = "/house/dogs/ralph/bone"
s = in_string.split("/")
out_strings = list(filter(None, ("/".join(s[:i+1]) for i in range(len(s)))))
print(out_strings)
#['/house', '/house/dogs', '/house/dogs/ralph', '/house/dogs/ralph/bone']

The filter(None, ...) is used to remove empty strings.

Or reverse the range if you want the output in the order you specified in your post:

out_strings = list(filter(None, ("/".join(s[:i]) for i in range(len(s), 0, -1))))
print(out_strings)
#['/house/dogs/ralph/bone',
# '/house/dogs/ralph',
# '/house/dogs',
# '/house']

pathlib — Object-oriented filesystem paths, How to effectively work with file system paths in Python 3 using the new "pathlib" Using the pathlib module, the two examples above can be rewritten using elegant, Maybe you need to list all files in a directory of a given type, find the parent is not iterable >>> cfg.read(str(path)) # Works on Python >= 3.4 ['config.​txt']. <iterable> is a collection of objects—for example, a list or tuple. The <statement(s)> in the loop body are denoted by indentation, as with all Python control structures, and are executed once for each item in <iterable>. The loop variable <var> takes on the value of the next element in <iterable> each time through the loop.

Something of a combination of the previous two answers:

import pathlib
import os
def resources(path):
  parts = pathlib.Path(path).parts
  for n in range(len(parts), 1, -1):
    yield os.path.join(*parts[:n])

The Path Class (The Java™ Tutorials > Essential Classes > Basic I/O), The result is a Counter object that shows the frequency of access for certain paths. One elegant way to make use of the multiprocessing module is to create a We've then mapped a function, analysis, to an iterable queue of work to be done, As the analysis() function returns a result, the parent process that created the  Python lists are incredibly versatile and have a lot of hidden tricks. Let’s explore some of these! 1. Filtering Lists with Python 1. a) With the Filter() Function. The filter() function takes two parameters: a function and an iterable item. In this case, we’ll define a function and filter a list. Let’s try this out with an example!

Python 3's pathlib Module: Taming the File System – Real Python, Comparing pathlib and os.path the right way; Normalizing file paths shouldn't be your from pathlib import Path Path('src/__pypackages__').mkdir(parents=True, to the Path constructor, we get the same representation in all cases: wouldn't be smart enough to convert that / into a \ in the path string. It takes a bit of time to get used to seeing / between what you might think of as strings. But remember that dirname isn't a string; rather, it's a Path object. And / is a Python operator, which means that it can be overloaded and redefined for different types. If you forget and try to treat your Path object as a string, Python will remind you:

Functional Python Programming: Discover the power of functional , When I discovered Python's new pathlib module a few years ago, I find all of these a bit awkward. import Path BASE_DIR = Path(__file__).resolve().parent.​parent Or you could use the read_text method on Path objects and a list The `Path` object is pretty smart about path separator normalization. Note: To re-iterate, __file__ returns the path relative to where the initial Python script was called. If you need the full system path, you can use os.getcwd() to get the current working directory of your executing code.

No really, pathlib is great, Must return an asynchronous iterator from its __aiter__() method. Without coercion, all arguments of even compatible types would have to be normalized usually comes from sys.path , but for subpackages it may also come from the parent but when the need arises, metaclasses can provide powerful, elegant solutions. Path.mkdir (mode=0o777, parents=False, exist_ok=False) ¶ Create a new directory at this given path. If mode is given, it is combined with the process’ umask value to determine the file mode and access flags.

Comments
  • Why can't you split the string on / and take slices?
  • I can. I'm looking for the best (pythonic) way to do it. My first thought is to split/join in a recursive function, yielding the result, but there's got to be a better way.
  • I've updated my answer to emphasize the non-file nature of pure posix paths
  • Curious: is there a reason that you are filtering instead of just referencing [:-1] since only the last element is empty?
  • @Bobby the delimiter can appear at the start or end of the string in a path. After the split, this causes empty strings. Using the filter I don't have to figure out which index to exclude, and it maintains the generator (which can't be indexed).
  • You might want to use '/'.join instead of os.path.join to make it OS independent. Then maybe strip off the first element?
  • I'm under the impression that os.path.join is OS independent, and that using '/' would make it OS-dependent (works in Unix based systems only). os.path.join also does the right thing with the top level element automatically.
  • @JeffreyFroman, I believe what @MadPhysicist is saying is that if you use os.path.join, the outcome will be different if you aren't on a *nix system. It's OS independence will make your solution not run on Linux.
  • Right, I undertsand that @Bobby: os.path.join will use the OS. path separator for that OS. If we ARE dealing with strings that are filesystem paths, then presumably those strings will include the separator appropriate to that OS. If the strings are not filesystem paths for the OS we'll be running on, then pathlib won't work at all, and we have to operate on raw strings and characters as such. We agree how os.path.join works -- if we're going to be using pathlib, we are already making the assumption that we're using a path appropriate to the OS we're running on.
  • @Bobby. The opposite. It will run as desired on Linux, but not on Windows. OP is looking for a forward slash separated path, on all systems.