【问题标题】:Pyinstaller and --onefile: How to include an image in the exe filePyinstaller 和 --onefile:如何在 exe 文件中包含图像
【发布时间】:2015-10-28 10:35:38
【问题描述】:

我已经使用 Pyinstaller 创建了一个 exe 文件。

pyinstaller.exe --onefile --icon='Loco.ico program.py

在程序中,我在绘图中包含一个图像,当我在其文件夹中单独运行程序时,我得到以下信息:

IOError: [Errno 2] No such file or directory: 'Logo.png'

一种解决方案是将图像包含在 exe 的文件夹中,如下面的链接所示:

pyinstaller does not show images and icon

但话说回来,--onefile 的重点就是完全拥有它,而不需要另外的图像。我认为解决方案可能在这个链接中,但我没有理解它。

Bundling data files with PyInstaller (--onefile)

我的规范文件如下所示:

# -*- mode: python -*-
a = Analysis(['AMOS_Visualizer.py'],
    pathex=['C:\\Users\\elu\\PycharmProjects\\Prosjektet\\Forsok splitting'],
    hiddenimports=[],
    hookspath=None,
    runtime_hooks=None)

pyz = PYZ(a.pure)
exe = EXE(pyz,
      a.scripts,
      a.binaries,
      a.zipfiles,
      a.datas,
      name='AMOS_Visualizer.exe',
      debug=False,
      strip=None,
      upx=True,
      console=True , icon='AMOS.ico')

【问题讨论】:

标签: python pyinstaller


【解决方案1】:

编辑:

我相信我找到了解决问题的方法。

# -*- mode: python -*-
a = Analysis(['AMOS_Visualizer.py'],
         pathex=['C:\\Users\\elu\\PycharmProjects\\Prosjektet\\Forsok splitting'],
         hiddenimports=[],
         hookspath=None,
         runtime_hooks=None)

for d in a.datas:
    if 'pyconfig' in d[0]:
        a.datas.remove(d)
        break

a.datas += [('Logo.png','C:\\Users\\elu\\PycharmProjects\\Prosjektet\\Forsok splitting\\Logo.png', 'Data')]
pyz = PYZ(a.pure)
exe = EXE(pyz,
      a.scripts,
      a.binaries,
      a.zipfiles,
      a.datas,
      name='AMOS_Visualizer.exe',
      debug=False,
      strip=None,
      upx=True,
      console=True, icon='C:\\Users\\elu\\PycharmProjects\\Prosjektet\\Forsok splitting\\AMOS.ico')

并将以下内容添加到我的 main.py 脚本中

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)

Logo = resource_path("Logo.png")

【讨论】:

    【解决方案2】:

    如果您使用 Qt Designer,您可以通过创建资源文件并将所需的所有图像(包括 Logo.png)添加到该资源来实现。

    要创建资源文件,您可以按照Inserting an image in GUI using QT Designer 中的步骤操作。

    在资源文件中插入图片后,将 Logo.png 分配给 Window 图标,保存 QtDesigner 界面并使用命令转换资源文件:pyrcc4 -py3 resourcetest.qrc -o resourcetest_rc.py

    最后,使用 --onefile 选项创建 exe 文件。无需编辑规范文件。

    【讨论】:

      【解决方案3】:

      这是以下内容的变体: Bundling data files with PyInstaller (--onefile), 并且给出的答案更清楚。

      两行:

      1. 您必须将图像文件添加到“数据”中(在您的规范中 文件或使用 PyInstaller 挂钩脚本)
      2. 如果它使用 sys._MEIPASS 存在,
        使用单行 base_path = getattr(sys, '_MEIPASS', '.')+'/' 获取“root_path”变量以连接到您的所有 文件的路径。
        那么,filepath = base_path + filepath

      【讨论】:

      • 如果您认为它是重复的,只需将其标记为这样。这里不需要重写答案。
      【解决方案4】:

      在“hiddenimports = []”之前添加“datas = ['您的文件的位置']”。会的。 在我的情况下,这有效

          # -*- mode: python -*-
      
      block_cipher = None
      
      
      a = Analysis(['embed.py'],
                   pathex=['C:\\Users\\Aravind\\Desktop\\exe'],
                   binaries=[],
                   datas=['C:\\Users\\Aravind\\Desktop\\exe\\dist\\map.png'],
                   hiddenimports=[],
                   hookspath=[],
                   runtime_hooks=[],
                   excludes=[],
                   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='embed',
                debug=False,
                strip=False,
                upx=True,
                runtime_tmpdir=None,
                console=True )
      

      【讨论】:

      • 我认为您需要使用元组 datas=[('C:\\Users\\Aravind\\Desktop\\exe\\dist\\map.png','.')], 并且您还需要首先使用 pyi -makespec --onefile file.py,编辑 .spec 文件以包含上述内容,然后构建 pysintaller - -options myfile.spec
      【解决方案5】:

      我尝试了很多,但一个小时后就奏效了:

      当我第一次运行我的程序文件 MilaBild.py 时:

      pyinstaller -F -w MilaBild.py
      

      创建“.spec”文件的接缝,我需要添加以下内容,如上面其他评论中所述:

      a.datas += [('rosa.png','C:\\Python34\\rosa.png', 'DATA')]
      

      我的图像文件的名称是 rosa.png。它与我的程序文件 MilaBild.py 位于同一目录中。

      然后我还必须在我的实际程序文件中添加上面注释中提到的部分:

      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)
      

      然后我添加了将文件获取到变量的部分并且它起作用了:

      rosa = resource_path("rosa.png")
      

      我尝试了很多,但完成这项工作花了我一个小时。稍后我将尝试使用两个图像、声音和子目录来制作它。但现在是 23 点 45 分,那将是另一天,到目前为止,我对此感到非常高兴,对我来说是一个很好的休息时间。

      【讨论】:

        【解决方案6】:

        最后它比我在各种网页和这里找到的更简单。

        1) 当代码作为已编译的可执行文件运行时,您在代码中指定临时目录中的相对路径:

        if getattr(sys, 'frozen', False): # Running as compiled
            running_dir = sys._MEIPASS + "/files/" # Same path name than pyinstaller option
        else:
            running_dir = "./" # Path name when run with Python interpreter
        iconFileName = running_dir + "mylogo.ico"
        if os.path.isfile(iconFileName):
            root.iconbitmap(iconFileName) # Exemple for tkinter usage
        

        2) 您在编译器选项中提供创建文件的临时目录中的路径:

        pyinstaller --onefile --add-binary "mylogo.ico;files" -i mylogo.ico myMainPrg.py
        

        这样,您不必知道文件在开发中的完整路径以及您将在生产中安装它们的位置。

        【讨论】:

          【解决方案7】:

          为此苦苦挣扎。要知道的关键是,对于 --onefile 构建,您的图像存储在 sys._MEIPASS 文件夹中。

          我的 tkinter 应用程序中的这行代码破坏了我的 .exe:

          self.wm_iconbitmap("favicon.ico")
          

          为了修复它,我将其替换为:

          self.wm_iconbitmap(get_path("favicon.ico"))
          

          get_path() 是我添加到模块中的一个小函数:

          def get_path(filename):
              if hasattr(sys, "_MEIPASS"):
                  return os.path.join(sys._MEIPASS, filename)
              else:
                  return filename
          

          对于上下文,我在 CLI 中运行此命令来构建 .exe:

          pyinstaller --noconfirm --onefile --windowed --add-data "C:/Users/[...]/favicon.ico;."  "C:/Users/[...]/main.py"
          

          注意,在 Win10 上运行。

          感谢许多其他 Stack Overflow 贡献者。

          【讨论】:

          • 这是正确的答案。目前接受的那个对我不起作用。
          【解决方案8】:

          当我尝试用一​​个小应用程序进行测试时,我在我的程序脚本中看到,我使用 C: 驱动器中的图像目录来引用图像,例如:

                xxx.setStyleSheet("background-image: url(C:\pictures\image1.jpg);"
          

          而我应该确保图像与我的 F: 驱动器中的项目文件位于同一文件夹中

          因此,当我将图像复制到 F: 驱动器中包含项目文件的同一文件夹时,我只是使用了:

             xxx.setStyleSheet("background-image: url(image1.jpg;")
          

          改成这种格式后效果很好

          我只将图像复制到项目文件夹中,而没有在我的代码引用中使用该路径,但之前在我的代码中使用 C: 目录来引用它。这就是它没有按预期工作的原因。

          所以在我的脚本中使用了正确的路径,我使用了这个命令:

               pyinstaller --windowed  --add-data "image1.jpg;." --add-data "image2.jpg;." --add-data "image3.jpg;." --icon=myLogo.ico myPythonFile.py
          

          我在我的程序中使用的所有头像和背景图像都显示在它们应该在应用程序中的区域,并且也可以在应用程序部署到的其他计算机上看到。

          请管理员允许。我决定放下它,因为我或我明天可能需要它。我看到的其他答案让我感到困惑和困难

          【讨论】:

            【解决方案9】:

            将图像转换为 base64 代码

            首先在单独的代码中使用同名库将您的图像转换为 base64 代码,然后将结果保存在另一个 python 文件中,以便您可以将其导入到您的主 python 文件中。这是必要的,否则在使用 pyinstaller 将 .py 转换为 .exe 并在新位置缺少图像时移动 exe 文件后,您将收到 file not found 错误。

            import base64
            pic = open('file.png', 'rb')
            content = f'img = {base64.b64encode(pic.read())}\n'
            pic.close()
            
            with open('pic2str.py', 'w') as f:
                f.write(content) 
            

            在您的主 python 文件中导入 base64 代码

            现在在你的主文件中导入变量,这样你的主代码中就不会使用你的图像文件地址了。

            from pic2str import img
            
            bg = base64.b64decode(img)
            image = tk.PhotoImage(data=bg)
            label = tk.Label(
                root,
                compound="center",
                text="Your Text",
                font=("Your Font", Your Font size),
                fg="Your Color",
                image=image)
            label.pack(fill="both", expand=1)
            

            现在您可以独立于您使用的图像使用转换为 .exe 的文件。

            【讨论】:

              【解决方案10】:

              无忧无虑。我有同样的问题并通过这样做得到了答案...... 复制我所有的图像并将它们粘贴到 pyinstaller 创建的 dist/ 和 build/ 目录中,问题就解决了。 :)

              【讨论】:

                猜你喜欢
                • 2017-05-21
                • 2022-07-07
                • 2016-12-14
                • 2013-05-18
                • 1970-01-01
                • 2020-12-17
                • 1970-01-01
                • 2018-07-06
                • 2014-01-03
                相关资源
                最近更新 更多