python pyinstaller 将 GUI 中的图像捆绑到 onefile EXE 中?

问题描述 投票:0回答:6

我已经从 python tkinter GUI 成功创建了一个包含图像的 EXE 文件。请参阅以下代码:

lblLogo=Label(main)
lblLogo.grid(row=3,column=11,rowspan=4)

try:
    filelocation="C:/Documents/Python/ScreenPartNumberProgram/"
    KasonLogo=PhotoImage(file=filelocation+"KasonLogo.png")
    KasonLogo=KasonLogo.zoom(25,20)
    KasonLogo=KasonLogo.subsample(50,50)
    lblLogo.config(image=KasonLogo)
    icon=PhotoImage(file=filelocation+"KasonLogo.png")
    main.tk.call('wm','iconphoto',main._w,icon)
except:
    print("warning: could not load photos")
    lblLogo.config(text="[KasonLogo.png]")

exe 文件在我的计算机上打开并完美运行。我用这个命令来获取.exe:

pyinstaller --onefile --noconsole myscript.py

唯一的问题是该文件要求图像位于同一文件夹中,否则不会显示在标签上。如何在不需要外部文件的情况下将图像捆绑到 EXE 中?

提前致谢

编辑: 我查看了提供的链接,做了更多研究,但仍然没有解决问题。仅当图像位于同一文件夹中时该程序才有效。我真的很想让它在不需要外部图像文件的情况下工作。 resources_path 技术似乎也不适合我......

我还尝试修改我的代码以使用 PIL 的 ImageTk 和同样的问题。仅当外部图像文件位于其文件夹中时,程序才会加载图像。

python tkinter exe photo
6个回答
7
投票

天哪!经过几天的头痛之后,我终于找到了一种有效的方法...这是我为使程序在不需要外部图像文件的情况下工作而所做的:

第一步:对图像文件进行编码(注意必须是GIF,可以使用paint进行转换):

import base64
with open("MyPicture.gif", "rb") as image_file:
    encoded_string = base64.b64encode(image_file.read())
print(encoded_string)#print string to copy it (see step 2)

第 2 步:下一步是将字符串复制并粘贴到单独的 myimages.py 文件中,然后 将其存储为变量。例如:

imageString = b'R0lGODlhyADIAPcAAAA .....blah blah really long string.......'

第3步:然后将myimages.py导入主程序并调用变量

from myimages import *
pic=imageString#GIF decoded to string. imageString from myimages.py
render = PhotoImage(data=pic)
myLabel.config(image=render)

第 4 步:在规范文件中:包含 myimages.py 作为数据

# -*- mode: python -*-

block_cipher = None

#instructions: pyinstaller --onefile --noconsole myProgram.spec

file_name = 'myProgram'
add_files=[('myimages.py','module')]

a = Analysis([file_name+'.py'],
             pathex=['C:\\Program Files (x86)\\Python36-32\\Scripts'],
             binaries=[],
             datas=add_files,
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=exclude_list,
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name=file_name,
          debug=False,
          strip=False,
          upx=True,
          runtime_tmpdir=None,
          console=False )

第5步:终于可以编译成EXE了:

pyinstaller --onefile --noconsole myProgram.spec

SIGH如果有人有更好的解决方案,请发布在这里。直到那时我很高兴有些东西起作用了......


2
投票

当我想包含一个 .ico 文件用作我的 tkinter 应用程序的图标时,我遇到了同样的问题。这是我让它工作的方法:

  1. 使用 PyInstaller 构建 .exe 文件时,我指定了 --add-data 选项以及 .ico 的完整路径。

  2. 当应用程序启动时,它必须将 .exe 中的所有内容解压到临时目录中,因此我获取该临时目录的路径并使用它来指定 .ico 文件的临时位置。

在主循环启动之前,使用“tempfile”获取临时文件目录并使用“glob”检查文件模式匹配:

tempdir = tempfile.gettempdir()
icon_path = tempdir + '\\' + 'next_subdirectory_pattern' + '\\' + '*.ico'
icon_matches = glob.glob(icon_path)
if len(icon_matches) > 0:
    logo = icon_matches[0]
else:
    logo = ''
tk.Tk.iconbitmap(self, default=logo)

可能不是最雄辩的方式,但它确实有效。


1
投票

我是这样做的......

将映像与可执行文件捆绑在一起:

使用以下命令将图标保存到名为“icon”的文件夹中,该文件夹将在 pyinstaller 运行时生成的“C:\Users\AppData\Local\Temp_MEI123456”文件夹中生成:

--add-data=C:\absolute\path\to\your\ICON.ico;icon

我的完整命令行,我在 python 终端(我使用 pycharm IDE)中输入的字符串来生成我的 EXE,如下所示:

pyinstaller -w -F -i=C:\absolute\path\to\your\ICON.ico --add-data=C:\absolute\path\to\your\ICON.ico;icon -n=MyEXEsNameV1 main.py

(对于调试,省略 -w 并添加 --debug=all 很有帮助)

文档参考:https://pyinstaller.readthedocs.io/en/stable/usage.html#options-group-what-to-bundle-where-to-search

访问我的 python 脚本 main.py 中的图像:

我使用以下代码来设置 tk 窗口:

import tkinter as tk
from os import path

    # main widget
    self.root = tk.Tk(master)
    self.root.title('Window Title Bar Name V1.0')
    self.root.minsize(1234, 1234)

    # get icon
    try:
        # Get the absolute path of the temp directory
        path_to_icon = path.abspath(path.join(path.dirname(__file__), 'icon/GAUGE-ICON.ico')) 
        # set the icon of the tk window
        self.root.iconbitmap(path_to_icon)
    except:
        pass

文档参考:https://pyinstaller.readthedocs.io/en/stable/runtime-information.html


0
投票

除了接受的答案之外,我想添加修改版本:

from PIL import Image, ImageTk

from res import *
#res is a module with your base64 image string and in my case variable is icon_base64
from base64 import b64decode

pic_as_bytes=ImageTk.BytesIO(icon_base64)
my_image=Image.open(pic_as_bytes)

请注意,此代码可以在 Python3 中运行,但不能在 Python2 中运行,因为它需要不同的方法和更多转换(下面的链接有一个 Python2 的示例)。

更多信息请参考 https://github.com/Ariel-MN/Tkinter_base64_Images/blob/master/tkinter_base64_image-ico.py


0
投票

我尝试了以下方法。第二个选项对我有用。

  1. 使用您提到的命令生成exe并将exe文件复制到项目的源文件夹(python文件所在的位置)。

  2. 我使用 auto-py-to-exe 修复它,它使用 pyinstaller。在那里你 可以看到生成的命令。

    pyinstaller --noconfirm --onedir --windowed --add-data "path/assets/"  "path/gui.py"
    

    首先,尝试使用

    --onefile
    而不是
    --onedir
    。我的没用 当我使用
    --onefile
    时。所以我必须隐藏
    --onedir


0
投票

我解决了类似的问题:我无法在我的 pyinstaller 生成的包中获取图像。

但事实上,它们被包含在与图像同名的子目录中。

代替:

pyinstaller [...] --add-data "logo.png:logo.png"

我必须:

pyinstaller [...] --add-data "logo.png:."

然后这个例子对我有用(注意:

logo.png
未提供):

#!/usr/bin/env python3
"""
REM Bundle using:
pyinstaller --onefile ^
   test.py ^
   --noconfirm --nowindow --windowed ^
   --add-data "logo.png:."
"""

import os
import sys
import tkinter as tk

IS_BUNDLED = hasattr(sys, "_MEIPASS")
BUNDLE_DIR = getattr(
    sys, "_MEIPASS", os.path.abspath(os.path.dirname(__file__))
)

IMAGE_PATH = "logo.png"


mainWindow = tk.Tk()

imagepath = os.path.abspath(os.path.join(BUNDLE_DIR, IMAGE_PATH))
img = tk.PhotoImage(file=imagepath)
tk.Label(mainWindow, image=img).grid(column=0, row=0)

mainWindow.mainloop()

我通过查看捆绑目录(

%_MEIPASS%
)发现了这一点,我发现图像路径是目录。

上面可能不需要使用“BUNDLE_DIR”,但它对我来说是有效的,并且对于某些读者来说可能是一个很好的提示。

© www.soinside.com 2019 - 2024. All rights reserved.