Pyinstaller错误打包

——来自GPT老师

PyInstaller 打包后 pathlib.Path(__file__) 无法正确获取路径的原因与解决方案

💡 问题原因

当你使用 PyInstaller--onefile(-F) 模式打包程序时,
PyInstaller 会在运行时自动将所有文件 临时解压 到一个随机生成的目录,例如:

C:\Users\<用户名>\AppData\Local\Temp\_MEI151002\

然后从这个临时目录中执行你的程序。
因此,执行以下代码时:

pathlib.Path(__file__)

返回的路径自然会是:

C:\Users\<用户名>\AppData\Local\Temp\_MEI151002\main.py

而不是你的项目原始目录。


✅ 正确的解决方案

要兼容 源码运行打包运行 两种情况,应使用以下写法:

import sys
import pathlib

if getattr(sys, 'frozen', False):
    # 如果是被打包的 exe 运行
    app_path = pathlib.Path(sys.executable).parent
else:
    # 如果是源码运行
    app_path = pathlib.Path(__file__).parent

print("程序运行目录:", app_path)

说明:

  • sys.frozen 是 PyInstaller 在运行时自动注入的标志。
  • sys.executable 指向当前可执行文件的完整路径。
  • __file__ 仅在源码状态下可用。

🧱 示例修正版

import sys
import pathlib

class Functions:
    def __init__(self):
        self.key_path = r"Software\Microsoft\Windows\CurrentVersion\Run"
        self.app_name = "DeviceUsageTime"
        
        if getattr(sys, 'frozen', False):
            # 打包后运行
            self.app_path = pathlib.Path(sys.executable).parent
        else:
            # 源码运行
            self.app_path = pathlib.Path(__file__).parent

        print("当前程序路径:", self.app_path)

🧠 为什么 PyInstaller 这么做?

--onefile 模式下,PyInstaller 会:

  1. 将所有依赖文件压缩进一个 EXE。
  2. 启动时解压到 _MEIxxxxx 临时文件夹。
  3. 从该文件夹运行虚拟环境。
  4. 程序退出后自动删除该文件夹。

因此,__file__ 永远会指向这个临时路径。

若要获取 真正的 EXE 所在目录(例如存放配置文件、日志、资源等),
请使用 sys.executable


🧩 推荐封装:资源路径函数

可以定义一个通用函数,在源码和打包模式下都能正确找到文件路径:

def resource_path(relative_path):
    """获取资源文件的绝对路径,兼容打包和源码运行"""
    import sys, pathlib
    if getattr(sys, 'frozen', False):
        base_path = pathlib.Path(sys.executable).parent
    else:
        base_path = pathlib.Path(__file__).parent
    return base_path / relative_path

使用方式:

config_file = resource_path("config.json")

这样即使打包成 EXE,也能正确读取配置文件或资源文件。


posted @ 2026-07-03 06:46  畅畅c  阅读(2)  评论(0)    收藏  举报