使用 Python 爬目录树

Climbing the directory tree with Python

假设我有这个文件夹结构:

My Project
├── One
│   ├── Another Thing
│   └── Two
│       ├── Three
│       │   └── foo.py
│       └── Whatever
└── Something Else

foo.py,使用Python 2,我怎样才能得到它所有父目录的列表?它应该看起来像这样:

['My Project', 'One', 'Two', 'Three']

当 Python 从磁盘上的文件加载它们时,您可以通过在所有 Python 模块上设置 __file__ attribute 来获取当前 Python 模块的路径。这是一个字符串,表示模块的源文件或 .pyc 字节缓存文件的绝对路径或相对路径(后者通常仅当它是 __main__ 脚本时)。

使用 os.path module 来 a) 确保路径是绝对路径,以及 b) 获取所有目录名称:

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

需要在 Windows 上调用 os.path.splitdrive(),其中网络 (UNC) 路径可以以 \hostname\mountC:\(驱动器号)开头。上面包括这样一个前缀作为第一个元素。拆分 UNC 前缀的另一个令人高兴的副作用是,这避免了 os.path.normpath() 不会用 [= 替换 os.altsep 分隔符(Windows 上的 /)的极端情况24=](Windows os.sep 值)如果路径以特殊的 \?\\.\ 前缀开头。

演示:

>>> __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']

在 Python 3.x 上,或者如果您准备安装一个 backport, you can also use the pathlib library; it provides Path instances that have a Path.parts attribute 为您提供完全相同的信息(根部分由 os.sep 或Windows 上的驱动器号或 UNC 路径):

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

(注:Path.parts产生元组,如果一定要列表,先把结果传给list())。

您可能还对 Path.parents sequence 感兴趣,它以相反的顺序为您提供了所有父目录作为 Path 个实例:

>>> 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('/')]

要获取列表中的目录列表,只需获取您当前的工作目录并与 /

拆分即可
In [6]: import os

In [7]: print os.getcwd().split(os.sep)[1:]
['home', 'rahul', 'Projects', 'Resume_parser', 'Code_base']

对于特定文件,

In [16]: print os.path.abspath('helpers.py').split(os.sep)[1:-1]
['home', 'rahul', 'Projects', 'Resume_parser', 'Code_base']