路径获取
import os
def get_base_path():
if getattr(sys, 'frozen', False):
# 打包后(PyInstaller / cx_Freeze 等)
app_dir = os.path.dirname(sys.executable)
else:
# 未打包,正常 Python 运行
app_dir = os.path.dirname(os.path.abspath(__file__))
return app_dir
说明
在 Python 打包成二进制(如使用 PyInstaller、cx_Freeze、Nuitka 等工具)后,__file__ 或 os.getcwd() 获取当前目录的方式可能失效或行为不一致,这是因为:
- 打包后的程序通常运行在一个临时解压目录(如
_MEIxxxxxx)中; __file__在 PyInstaller 的--onefile模式下可能指向临时路径;os.getcwd()返回的是启动时的工作目录,不是程序所在目录。
✅ 正确获取“程序所在目录”的方法(兼容打包前后)
方法一:使用 sys.executable(推荐)
import os
import sys
def get_app_dir():
if getattr(sys, 'frozen', False):
# 打包后(PyInstaller / cx_Freeze 等)
app_dir = os.path.dirname(sys.executable)
else:
# 未打包,正常 Python 运行
app_dir = os.path.dirname(os.path.abspath(__file__))
return app_dir
# 使用示例
APP_DIR = get_app_dir()
config_path = os.path.join(APP_DIR, "config.ini")
print("程序目录:", APP_DIR)
✅ 适用于 PyInstaller(
--onefile或--onedir)、cx_Freeze、auto-py-to-exe 等主流打包工具。
方法二:使用 sys._MEIPASS(仅 PyInstaller 特有)
如果你需要访问打包进去的资源文件(如图片、配置文件),PyInstaller 会把它们解压到 sys._MEIPASS 目录:
import sys
import os
def resource_path(relative_path):
"""获取资源文件的绝对路径(兼容打包前后)"""
try:
# PyInstaller 创建临时文件夹 _MEIPASS
base_path = sys._MEIPASS
except AttributeError:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
# 示例:读取同目录下的 logo.png
logo_path = resource_path("logo.png")
⚠️ 注意:
sys._MEIPASS只在 PyInstaller 打包后存在,且只用于被--add-data打包进去的资源。
❌ 常见错误做法
# 错误1:直接用 __file__
current_dir = os.path.dirname(__file__) # 打包后可能指向临时目录或报错
# 错误2:只用 os.getcwd()
current_dir = os.getcwd() # 返回的是用户在哪里双击运行程序的目录,不是程序所在位置
补充:PyInstaller 打包命令示例
# 打包单文件,并包含 config.ini 到根目录
pyinstaller --onefile --add-data "config.ini;." your_script.py
然后在代码中用 resource_path("config.ini") 访问。
总结
| 场景 | 推荐方法 |
|---|---|
| 获取程序 exe 所在目录(用于写日志、读外部配置) | os.path.dirname(sys.executable) |
| 获取打包进 exe 的资源文件路径(如图片、音效) | sys._MEIPASS + relative_path(用 resource_path 函数封装) |
这样就能确保无论是否打包,你的程序都能正确找到所需文件。

被折叠的 条评论
为什么被折叠?



