HOWTO · Python

如何获得当前 Python 脚本文件的文件夹路径

本贴士介绍了如何来获得 Python 当前脚本文件的文件夹路径。

本页内容

要获取正在运行的 Python 脚本所在目录,可以使用 os.path.dirname(os.path.abspath(__file__)),也可以使用 Path(__file__).resolve().parent。这两种写法都以 __file__(与脚本关联的路径)为起点,得出脚本所在目录。然后可以用该目录构造指向脚本旁边文件的路径。

获取当前脚本所在目录

脚本目录就是包含其 .py 文件的文件夹。__file__ 提供脚本路径;先应用 os.path.abspath(),再应用 os.path.dirname(),即可得到绝对目录路径。当脚本需要读取附近的配置、输入或数据文件时,这种写法很实用。如果 __file__ 是相对路径,os.path.abspath() 会根据进程的工作目录解析它,因此结果可能取决于启动 Python 时所在的位置。如果 __file__ 已经是绝对路径,工作目录就不会决定它的位置。

请在已保存的 Python 文件中运行此示例。代码块及其输出中的可见标签保留英文。

本节中的代码以及显示的标签或输出仍为英文。

import os

script_path = os.path.abspath(__file__)
script_directory = os.path.dirname(script_path)
directory, filename = os.path.split(script_path)

print("Script directory:", script_directory)
print("Directory and filename:", directory, filename)
Script directory: /work
Directory and filename: /work case-0.py

os.path.abspath() 会根据当前进程的上下文将脚本路径转换为绝对路径,os.path.dirname() 则提取其中的目录部分。os.path.split() 会分别返回目录和文件名。打印出的目录取决于文件的保存位置,因此没有适用于所有情况的固定输出可供照抄。输出中的标签仍为英文。

区分脚本目录与工作目录

工作目录是进程用于解析相对路径的位置,例如 open("data.csv") 中的路径。可以通过 os.getcwd() 查看工作目录。它可能是终端当前所在的文件夹、IDE 中设置的目录,也可能是父进程选定的目录;它不一定就是脚本所在的文件夹。

相比之下,__file__ 指的是正在运行的 Python 文件的路径。如果脚本位于 /projects/tool,但启动时的工作目录是 /tmp,那么相对路径打开 data.csv 时会从 /tmp 查找;根据脚本目录构造的路径则指向 /projects/tool。应根据文件的预期位置选择路径基准。若文件与脚本放在一起,可以使用 os.path.join(script_directory, "data.csv") 将文件名与推导出的脚本目录组合起来。

从 __file__ 推导出绝对路径,并不保证文件一定存在,也不能解决所有符号链接或部署相关的问题。这个路径只是一个可用作基准的位置;请根据应用的需要检查或打开最终路径。

使用 os.path 获取脚本目录

上面的示例保留了中间值,以便看清每一步操作。如果只需要脚本所在目录,可以将调用合并为 os.path.dirname(os.path.abspath(__file__))。如果目录和文件名都有用,则保留 os.path.split() 的结果,不要丢弃文件名。

要构造指向同目录文件的路径,应使用 os.path.join(),而不是用斜杠拼接字符串。这样 Python 会按照当前平台的路径分隔符规则处理路径。例如,os.path.join(script_directory, "settings.json") 会生成一个以脚本目录为基准的路径。直接传给 open() 的相对文件名则会从工作目录解析。

使用 pathlib 获取脚本目录

pathlib 使用路径对象表达相同的操作。在已保存的脚本中,Path(__file__).resolve().parent 就是脚本所在目录:resolve() 会获得解析后的绝对路径,.parent 则选取其父文件夹。可以用 / 添加子路径,例如 script_directory / "settings.json",再将生成的 Path 传给接受路径类对象的 API,包括 open()。

对应的表达式是 Path(__file__).resolve().parent;使用前请从 pathlib 导入 Path。如果周围代码已经使用 Path 对象,优先考虑 pathlib;如果处理的是字符串路径或要求字符串路径的现有 API,则可以使用 os.path。这两种方式都不会更改进程的工作目录。

处理笔记本和其他执行环境

Python 运行已保存的脚本时通常会定义 __file__,但交互式解释器和笔记本内核可能不会定义它。在这些环境中,上述基于脚本的写法无法以可移植的方式确定笔记本文件的位置。os.getcwd() 仍会返回进程的工作目录,可用于查找相对于内核当前目录的文件,但它不能代替笔记本源文件的路径。

如果要定位的文件不是正在运行的脚本,应从该文件已知的路径出发,而不是使用 __file__;然后用 os.path.dirname() 或 Path 对象的 .parent 获取其目录。请明确路径来源,让后续读者能够分辨它表示的是脚本、其他文件,还是进程的工作目录。