Issue
Let's say I have this folder structure:
My Project
├── One
│ ├── Another Thing
│ └── Two
│ ├── Three
│ │ └── foo.py
│ └── Whatever
└── Something Else
From foo.py
, using Python 2, how would I get a list of all its parent directories? It should look something like this:
['My Project', 'One', 'Two', 'Three']
Solution
You can get the path of the current Python module by using the __file__
attribute set on all Python modules when Python loads them from a file on disk. This is a string representing the absolute or relative path (the latter usually only when it's the __main__
script) to the source file or .pyc
byte-cache file of the module.
Use the os.path
module to a) ensure that the path is absolute, and b), get all the directory names:
import os
HERE = os.path.dirname(os.path.abspath(__file__))
def path_list(pathname):
drive, directory = os.path.splitdrive(pathname)
path = [] if not drive else [drive]
# with no UNC prefix, normpath guarantees the path uses os.sep
path += filter(None, os.path.normpath(directory).split(os.sep))
return path
The os.path.splitdrive()
call is needed to on Windows, where network (UNC) paths can start with \\hostname\mount
or with C:\\
(drive letters). The above includes such a prefix as the first element. Another happy side-effect of splitting of a UNC prefix is that this avoids one corner-case where os.path.normpath()
would not replace os.altsep
separators (/
on Windows) with \
(the Windows os.sep
value) if the path starts with the special \\?\
or \\.\
prefixes.
Demo:
>>> __file__ = os.path.join(os.sep, 'My Project', 'One', 'Two', 'Three', 'foo.py')
>>> __file__
'/My Project/One/Two/Three/foo.py'
>>> HERE = os.path.dirname(os.path.abspath(__file__))
>>> HERE
'/My Project/One/Two/Three'
>>> path_list(HERE)
['My Project', 'One', 'Two', 'Three']
On Python 3.x, or if you are prepared to install a backport, you can also use the pathlib
library; it provides Path
instances that have a Path.parts
attribute that gives you exactly the same info (with the root part represented by os.sep
or the drive letter or UNC path on Windows):
try:
from pathlib import Path
except ImportError:
# pathlib2 backport
from pathlib2 import Path
HERE = Path(__file__).resolve().parent
path_list = HERE.parts[1:] if HERE.root else HERE.parts
(Note: Path.parts
produces a tuple, if you must have a list, pass the result to list()
first).
You may also be interested in the Path.parents
sequence, which gives you all the parent directories as Path
instances, in reverse order:
>>> from pathlib import Path
>>> HERE = Path(__file__).resolve().parent
>>> HERE
PosixPath('/My Project/One/Two/Three')
>>> HERE.parts[1:] if HERE.root else HERE.parts
('My Project', 'One', 'Two', 'Three')
>>> list(HERE.parents)
[PosixPath('/My Project/One/Two'), PosixPath('/My Project/One'), PosixPath('/My Project'), PosixPath('/')]
Answered By - Martijn Pieters
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.