查找当前目录和文件所在的目录

2960

我如何确定:

  1. 当前目录(在运行Python脚本时所在的shell中),以及
  2. 我正在执行的Python文件的位置?

9
导入 os pwd = os.getcwd() # 在 Python 中将 cwd 转换为 pwd - Charlie Parker
这个问题显然是两个问题,应该被关闭并需要更多的关注。两个问题都是简单的参考问题,因此应该有单独的规范答案,以便可以用重复锤进行重复。然而,我一直在努力寻找仅限于第一个问题的适当规范答案,但是我发现了无数第二个问题的重复,其中大部分涉及到OP没有意识到存在差异 - Karl Knechtel
我在经过数小时的搜索后,尽力找到了最好的答案:“如何确定当前目录?答案是使用os.getcwd()”。唉。 - Karl Knechtel
13个回答

4623

要获取 Python 文件所在目录的完整路径,请在该文件中编写以下代码:

import os 
dir_path = os.path.dirname(os.path.realpath(__file__))

请注意,如果您已经使用 os.chdir() 来更改当前工作目录,则上述咒语将不起作用。因为 __file__ 常量的值是相对于当前工作目录的,并且不会受到 os.chdir() 调用的影响。


要获取当前工作目录,请使用

import os
cwd = os.getcwd()

上面使用的模块、常量和函数的文档参考资料:


194
当我使用这个来追加sys.path时,我很讨厌它。现在感觉很不舒服。 - FlipMcF
14
如果从IDE(例如IDLE)中调用,__file__将无法正常工作。建议使用os.path.realpath('./')或os.getcwd()。最佳答案在这里:https://dev59.com/enE85IYBdhLWcg3wvGOm?lq=1 - Neon22
3
@Neon22可能适用于某些需求,但我认为应该指出这些东西并不完全相同-文件可以在工作目录之外。 - Mark
2
@Moberg 经常情况下,使用dirname反转realpath时路径是相同的,但当文件(或其目录)实际上是符号链接时,它将会有所不同。 - Lekensteyn
7
出现错误 NameError: name '__file__' is not defined。如何解决? - Mohammad ElNesr
显示剩余9条评论

379

358
您可能会发现这对您有用作为参考:
import os

print("Path at terminal when executing this file")
print(os.getcwd() + "\n")

print("This file path, relative to os.getcwd()")
print(__file__ + "\n")

print("This file full path (following symlinks)")
full_path = os.path.realpath(__file__)
print(full_path + "\n")

print("This file directory and name")
path, filename = os.path.split(full_path)
print(path + ' --> ' + filename + "\n")

print("This file directory only")
print(os.path.dirname(full_path))

12
__file__ 在这里代表什么意思?但它对我不起作用。 - Alex Raj Kaliamoorthy
13
__file__ 是模块对象的一个属性。你需要在 Python 文件内运行代码,而不是在 REPL 上运行。 - Daniel Reis

291

pathlib模块是在Python 3.4中引入的PEP 428 — The pathlib module — object-oriented filesystem paths),它使得与路径相关的操作变得更加简单易用。

pwd

/home/skovorodkin/stack

tree

.
└── scripts
    ├── 1.py
    └── 2.py

为了获取当前工作目录,请使用 Path.cwd()
from pathlib import Path

print(Path.cwd())  # /home/skovorodkin/stack

使用Path.resolve()方法获取脚本文件的绝对路径:
print(Path(__file__).resolve())  # /home/skovorodkin/stack/scripts/1.py

要获取脚本所在目录的路径,请访问 .parent(建议在调用 .parent 之前调用 .resolve()):

print(Path(__file__).resolve().parent)  # /home/skovorodkin/stack/scripts

请记住,在某些情况下,__file__是不可靠的:如何在Python中获取当前执行文件的路径?


请注意,Path.cwd()Path.resolve()和其他Path方法返回路径对象(在我的情况下是PosixPath),而不是字符串。在Python 3.4和3.5中,这会导致一些问题,因为open内置函数只能处理字符串或字节对象,并不支持Path对象,所以你必须将Path对象转换为字符串或使用Path.open()方法,但后一种选项需要更改旧代码:

文件 scripts/2.py

from pathlib import Path

p = Path(__file__).resolve()

with p.open() as f: pass
with open(str(p)) as f: pass
with open(p) as f: pass

print('OK')

输出

python3.5 scripts/2.py

Traceback (most recent call last):
  File "scripts/2.py", line 11, in <module>
    with open(p) as f:
TypeError: invalid file: PosixPath('/home/skovorodkin/stack/scripts/2.py')

正如您所看到的,open(p)在Python 3.5中无法使用。

PEP 519 — 添加文件系统路径协议,在Python 3.6中实现,添加了对PathLike对象的支持到open函数,因此现在您可以直接将Path对象传递给open函数:

python3.6 scripts/2.py

OK

7
请注意,这些方法可以链式使用,因此您可以将 app_path = Path(__file__).resolve().parent.parent.parent../../../ 并列使用,如果需要的话。 - shacker
什么系统有名为"python3.5"和"python3.6"的可执行文件(或等效文件)?Ubuntu Ubuntu MATE 20.04 (Focal Fossa)没有(至少默认情况下没有)。它有名为"python3"和"python2"的可执行文件(但没有名为"python"的 - 这会导致某些问题)。 - Peter Mortensen
@PeterMortensen,感谢您的纠正。我不记得那时候是否实际上有python3.x符号链接。也许我认为这会使代码片段对读者更清晰一些。 - skovorodkin

82
  1. 获取当前目录的完整路径

>>import os
>>print os.getcwd()

输出:"C:\Users\admin\myfolder"

  • 只获取当前目录的文件夹名称

    >>import os
    >>str1=os.getcwd()
    >>str2=str1.split('\\')
    >>n=len(str2)
    >>print str2[n-1]
    

    输出:"myfolder"


  • 13
    os.getcwd().split('\\')[-1] - imkost
    60
    最好使用os.sep而不是在Windows上硬编码:os.getcwd().split(os.sep)[-1] - kkurian
    6
    这种方法的问题在于,如果你从不同的目录执行脚本,你会得到该目录的名称,而不是脚本的名称,这可能不是你想要的。 - airstrike
    1
    对的,当前托管文件的目录可能不是您的CWD。 - f0ster

    57

    可以使用Pathlib这样的方式来获取包含当前脚本的目录:

    import pathlib
    filepath = pathlib.Path(__file__).resolve().parent
    

    我喜欢这个解决方案。然而,它可能会引起一些Python 2.X的问题。 - Kimmo Hintikka
    1
    对于 Python 3.3 及更早版本,需要安装 pathlib。 - A. Romeu
    7
    @Kimmo 你唯一应该使用 Python 2 代码的原因是将其转换为 Python 3。 - kagronick
    @kagnirick同意,但仍有人不同意。我使用Python 3.6的格式化字符串字面值(PEP 498)编写所有新代码,以防止有人将它们推到Python2。 - Kimmo Hintikka
    请注意,这些方法是可链接的,因此如果需要,您可以将app_path = Path(__file__).resolve().parent.parent.parent用作../../../的并列方法。 - shacker
    当我在Jupyter Notebook中运行代码时,出现错误:NameError: name '__file__' is not defined,如何解决? - XYZ

    43
    如果您正在尝试查找当前文件所在的目录:
    跨平台的方法:
    dirname, filename = os.path.split(os.path.abspath(__file__))
    

    38

    获取当前目录的完整路径:

    os.path.realpath('.')
    

    10
    这个可以在Jupyter iPython笔记本中运行(´__file__´和getcwd不行)。 - Oliver Zendel
    3
    仍然有效。来自未来的感谢,@OliverZendel! - yoann-h
    4
    我正在使用Jupyter Notebook远程工作:os.getcwd()os.path.realpath('.')返回完全相同的路径字符串。 - Leevo
    @Leevo:重点是什么? - Peter Mortensen
    这会返回 Jupyter 的根目录,而不是包含该文件的目录。 - Scott

    38
    如果您正在使用Python 3.4,那么全新的高级pathlib模块可让您方便地调用pathlib.Path.cwd()来获取代表当前工作目录的Path对象,以及许多其他新功能。
    有关此新API的更多信息,请在此处查看。

    3
    对于 Python 版本小于 3.4,您可以使用 pathlib2 库:https://pypi.python.org/pypi/pathlib2/。 - Eyal Levin

    34

    问题1的答案:

    如果你想获取当前目录,可以这样做:

    import os
    os.getcwd()
    
    如果你只想要任何文件夹名称,并且你已经有了该文件夹的路径,请按照以下步骤操作:

    如果您想要仅获取文件夹名称并且拥有该文件夹的路径,请执行以下操作:

    def get_folder_name(folder):
        '''
        Returns the folder name, given a full folder path
        '''
        return folder.split(os.sep)[-1]
    

    答案 #2:

    import os
    print os.path.abspath(__file__)
    

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