Python:获取两级目录上层目录

154

好的...我不知道模块x在哪里,但是我知道我需要获取到上两级目录的路径。

那么,是否有更加优雅的方法来实现:

import os
two_up = os.path.dirname(os.path.dirname(__file__))

欢迎提供适用于Python 2和3的解决方案!


2
我认为你的解决方案非常棒。pathlib 解决方案更加优雅和可读,但是它并未包含在 Python 2.7 中。我建议坚持使用你现有的方案,或者加上注释。 - jme
或许值得添加 pip install pathlib2 选项以保持在2.7中的正常。 - jonathan
如果您想获取当前工作目录的上两级目录,可以完美地使用以下代码:os.path.abspath(os.path.join(os.getcwd(), os.path.pardir, os.path.pardir)) - Elias
18个回答

210
你可以使用 pathlib。不幸的是,这只在 Python 3.4 的标准库中可用。如果你使用较旧版本的 Python,则需要从这里安装一个副本。使用 pip 应该很容易完成。
from pathlib import Path

p = Path(__file__).parents[1]

print(p)
# /absolute/path/to/two/levels/up

这里使用了parents序列,提供了访问父目录的方式,并选择了上面第二个。

请注意,在这种情况下,p将是某种Path对象,具有其自己的方法。如果需要将路径作为字符串,则可以在它们上调用str


20
这不应该成为被接受的答案,因为Path类的parents方法取决于执行位置。如果你在当前目录下执行__file__,那么Path类将没有父级路径。要么接受@Sebi2020的答案,要么使用你最初的方法。我认为你最初的方法更易读。 - Red-Tune-84
1
你可能需要执行 p = Path(os.path.abspath(__file__)).parents[1] - Adam Raudonis
6
您可以使用 Path(__file__).resolve().parents[1] 代替 os.path.abspath。这个方法能够得到相同的结果,更加简洁和易于理解。 - Tulio Casagrande
10
正如@Kazanz所提到的那样,当从其他路径执行时,这种解决方案不起作用。最好的解决方案是:p = Path(__file__).resolve().parents[1]。我也将其添加为答案。 - pythinker
请注意,parents[x]的返回类型不是字符串,而是PurePath的实现。您可以随时调用str以获取实际值。 - Fabrice E.
显示剩余4条评论

79

非常简单:

这是你想要的内容:

import os.path as path

two_up =  path.abspath(path.join(__file__ ,"../.."))

14
也许可以使用os.pardir而不是.. - jme
sys.argv[0]不会返回由python.exe运行的模块吗?如果我感兴趣的模块是从其他包中导入的,那么这并不一定适用。我的理解正确吗? - jramm
2
@jme,你知道有没有一种操作系统,可以用除了“..”之外的其他字符串来获取父目录吗? - Sebi2020
1
@Sebi2020 是的,尤其是旧版的Mac OS。这里有一个列表:https://en.wikipedia.org/wiki/Path_(computing) - jme
__file__和其他内容连接起来并不总是会得到有效的路径。 - ebk
显示剩余5条评论

33

我原本只是想加上这个东西来卖个傻,但同时也因为它展示了别名函数和/或导入在潜在实用性方面对新手的帮助。

写完后,我认为这段代码比迄今为止其他答案更易读(即理解意图所需的时间更短),而可读性通常是至关重要的。

from os.path import dirname as up

two_up = up(up(__file__))

注意:只有在你的模块非常小或者上下文一致时,才需要这样做。


32

从任何目录执行时,Python版本大于等于3.4的最佳解决方案是:

from pathlib import Path
two_up = Path(__file__).resolve().parents[1]

11

获取向上 2 级目录:

 import os.path as path
 curr_dir=Path(os.path.dirname(os.path.abspath(__file__)))
 two_dir_up_=os.fspath(Path(curr_dir.parent.parent).resolve())

我已经采取了以下措施,向上提升两个级别并钻取到其他目录

 default_config_dir=os.fspath(Path(curr_dir.parent.parent,
                                   'data/config').resolve()) 

文件的位置和当前工作目录不一定相同,因此您的解决方案并不总是产生相同的结果。 - Sebi2020
相对于工作目录而非模块,给出路径。 - jramm

4

个人而言,我发现使用 os 模块是最简单的方法,如下所述。如果您只需要上升一个级别,请将 ('../..') 替换为 ('..')。

    import os
    os.chdir('../..')

--Check:
    os.getcwd()

3
硬编码 '/' 是可接受的吗? 我本来期望会看到 os.chdir(os.path.join('..', '..'))。 - GreenAsJade
相对于工作目录而非模块,给出路径。 - jramm

4

更多跨平台实现将会:

import pathlib
two_up = (pathlib.Path(__file__) / ".." / "..").resolve()

在Windows上不支持使用parent。此外需要添加.resolve(),以便:

将路径变为绝对路径,在此过程中解决所有符号链接,并进行归一化处理(例如,在Windows下将斜杠转换为反斜杠)


3
你是否有“parent”在Windows上无法使用的来源?自从你写这条评论以来,这个问题似乎已经被解决了。我使用Python 3.7.2在Windows 10上没有遇到任何问题。 - Nathan
我在Windows 10上使用Python 3.6.5成功运行了parent。 @Zhukovgeen,你说的是哪个版本的Python? - ggulgulia
@ ggulgulia 我相信它是3.7。 - zhukovgreen

3

(pathlib.Path('../../') ).resolve()


相对于工作目录而非模块,给出路径。 - jramm

3

令人惊讶的是,似乎还没有人探索过这个不错的一行代码选项:

import os
two_up = os.path.normpath(__file__).rsplit(os.sep, maxsplit=2)[0]

rsplit 是一个有趣的函数,因为 maxsplit 参数直接表示向上移动多少级父文件夹,并且它总是在一次路径遍历中返回结果。


2

100%工作答案:

os.path.abspath(os.path.join(os.getcwd() ,"../.."))

1
不,这会获取相对于当前工作目录的两个级别的目录,而不是当前模块。 - jramm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接