很多人会误以为它是一个函数,但实际上 __file__ 是一个 Python 内置变量,它存储了当前执行脚本的文件路径。

核心概念:__file__ 是什么?
__file__ 是一个全局变量,当 Python 解释器执行一个模块(通常是 .py 文件)时,这个变量就会被自动创建并赋值,它的值就是该模块源文件的路径。
重要提示:__file__ 的行为会因 Python 的运行方式而异。
直接运行脚本
当你直接在命令行运行一个 Python 脚本时,__file__ 的值是脚本的相对路径或绝对路径。
示例:

假设你有一个文件结构如下:
/my_project/
└── main.py
main.py 的内容如下:
# main.py
import os
print(f"当前文件的路径是: {__file__}")
# 获取脚本所在的目录
script_dir = os.path.dirname(__file__)
print(f"脚本所在的目录是: {script_dir}")
# 获取脚本所在的绝对目录
abs_script_dir = os.path.abspath(script_dir)
print(f"脚本所在的绝对目录是: {abs_script_dir}")
在终端运行:
# 假设你当前在 /my_project 目录下 python main.py
输出结果:

当前文件的路径是: main.py
脚本所在的目录是:
脚本所在的绝对目录是: /my_project
分析:
__file__是main.py,这是一个相对路径。os.path.dirname(__file__)获取了文件名之前的路径部分,因为main.py在当前工作目录,所以为空。os.path.abspath()将相对路径转换为了绝对路径。
作为模块导入
当你将一个脚本作为模块导入到另一个脚本中时,__file__ 的值是被导入模块的文件路径。
示例:
文件结构如下:
/my_project/
├── main.py
└── utils/
└── helper.py
utils/helper.py 的内容:
# utils/helper.py
import os
print(f"在 helper.py 中,__file__ 的值是: {__file__}")
main.py 的内容:
# main.py
import os
from utils import helper
print(f"在 main.py 中,__file__ 的值是: {__file__}")
在终端运行 main.py:
python /my_project/main.py
输出结果:
在 helper.py 中,__file__ 的值是: /my_project/utils/helper.py
在 main.py 中,__file__ 的值是: /my_project/main.py
分析:
- 在
main.py中,__file__指向main.py自身。 - 当
main.py导入helper.py时,在helper.py的内部,__file__指向helper.py的完整路径。
在交互式解释器中
如果你在 Python 的交互式 shell (REPL) 中直接输入 __file__,会抛出 NameError,因为它不是一个全局变量,只有在模块被加载时才会被创建。
>>> __file__ Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name '__file__' is not defined
__file__ 的常见用途
__file__ 最常见的用途是确定脚本的位置,以便正确地访问其他文件,如配置文件、数据文件、日志文件等。
最佳实践:使用 pathlib 模块
现代 Python (3.4+) 推荐使用 pathlib 模块来处理路径,它比传统的 os.path 更直观、更强大。
示例:使用 pathlib
假设项目结构如下:
/my_project/
├── main.py
└── data/
└── config.json
main.py 的内容:
# main.py
from pathlib import Path
# 获取当前脚本所在的目录
# Path(__file__).parent 等价于 os.path.dirname(__file__)
# 但 Path 对象可以进行更方便的操作
script_dir = Path(__file__).parent
# 构建配置文件的绝对路径
config_file_path = script_dir / 'data' / 'config.json'
print(f"当前脚本目录: {script_dir}")
print(f"配置文件路径: {config_file_path}")
# 检查文件是否存在
if config_file_path.exists():
print("配置文件找到了!")
else:
print("配置文件未找到!")
# 读取文件内容(仅作演示)
try:
with open(config_file_path, 'r', encoding='utf-8') as f:
print("\n文件内容:")
print(f.read())
except FileNotFoundError:
print("\n无法读取文件,因为它不存在。")
运行 main.py 后的输出:
当前脚本目录: /my_project
配置文件路径: /my_project/data/config.json
配置文件找到了!
{
"database": "localhost",
"port": 5432
}
重要注意事项:__file__ 的局限性
-
在打包后的应用中 (PyInstaller, PyOxidizer) 当你使用工具(如 PyInstaller)将你的 Python 程序打包成一个独立的可执行文件(如
.exe或.app)后,__file__的行为会变得复杂,它可能指向一个临时的解压目录,而不是原始的脚本路径,在这种情况下,不应依赖__file__来定位资源文件。 -
__file__可能不是真实路径 在某些情况下(从标准输入读取代码,或者在交互式环境中运行代码片段),__file__可能不会被定义,或者其值可能不是你期望的文件路径('<stdin>'或'<string>'),在访问它之前最好进行检查。# 安全地使用 __file__ if '__file__' in globals(): script_dir = Path(__file__).parent # ... 进行后续操作 ... else: print("无法确定脚本路径,可能正在交互式环境中运行。") # 提供一个备选方案,例如使用当前工作目录 script_dir = Path.cwd()
| 特性 | 描述 |
|---|---|
| 类型 | 内置变量,不是函数。 |
| 作用 | 存储当前执行的 Python 模块的源文件路径。 |
| 运行方式 | 直接运行脚本时,值为脚本的路径;作为模块导入时,值为被导入模块的路径。 |
| 主要用途 | 定位脚本自身,以便访问同目录或子目录下的其他文件(如配置、数据、日志等)。 |
| 推荐用法 | 结合 pathlib 模块 (Path(__file__).parent) 来安全、方便地处理文件路径。 |
| 局限性 | 在打包后的应用或某些非标准执行环境中可能不可靠或未定义。 |
