使用PyInstaller捆绑数据文件(onefile)

2024-04-25 19:10:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用PyInstaller构建一个包含图像和图标的单文件EXE。我一生都无法让它与--onefile一起工作

如果我这样做--onedir,它会工作得很好。 当我使用--onefile时,它找不到引用的其他文件(在运行编译的EXE时)。它发现DLL和其他一切都很好,只是没有两个图像

我查看了运行EXE时生成的temp dir(例如\Temp\_MEI95642\),文件确实在那里。当我把EXE放到那个临时目录中时,它会找到它们。非常令人困惑

这是我添加到.spec文件中的内容

a.datas += [('images/icon.ico', 'D:\\[workspace]\\App\\src\\images\\icon.ico',  'DATA'),
('images/loaderani.gif','D:\\[workspace]\\App\\src\\images\\loaderani.gif','DATA')]     

我应该补充一点,我也尝试过不把它们放在子文件夹中,没有什么不同

编辑:由于PyInstaller更新,将更新的答案标记为正确


Tags: 文件图像srcappdatagifexeworkspace
3条回答

pyinstaller将数据解压到临时文件夹中,并将此目录路径存储在_MEIPASS2环境变量中。要在打包模式下获取_MEIPASS2目录,并在解包(开发)模式下使用本地目录,我使用以下方法:

def resource_path(relative):
    return os.path.join(
        os.environ.get(
            "_MEIPASS2",
            os.path.abspath(".")
        ),
        relative
    )

输出:

# in development
>>> resource_path("app_icon.ico")
"/home/shish/src/my_app/app_icon.ico"

# in production
>>> resource_path("app_icon.ico")
"/tmp/_MEI34121/app_icon.ico"

在应用程序未安装的情况下(即未设置sys._MEIPASS),所有其他答案都使用当前工作目录。这是错误的,因为它阻止您从脚本所在目录以外的目录运行应用程序

更好的解决方案:

import sys
import os

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, relative_path)

PyInstaller的较新版本不再设置env变量,因此Shish的优秀answer将无法工作。现在,路径被设置为sys._MEIPASS

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

相关问题 更多 >

    热门问题