使用PyInstaller为Kivy应用程序生成单个exe文件

3

我有一个简单的kivy应用程序,希望生成一个单独的exe文件。

我使用virtualenv --python=C:\Python27\python.exe <path/to/new/virtualenv/>创建了一个虚拟环境。然后我激活该环境。

在虚拟环境中,我安装了以下模块:

python -m pip install --upgrade pip wheel setuptools

python -m pip install docutils pygments pypiwin32 kivy.deps.sdl2 kivy.deps.glew --extra-index-url https://kivy.org/downloads/packages/simple/

python -m pip install kivy

pip install pyinstaller

我接下来有以下文件。

touch.py 文件包含以下代码:

import ctypes
import kivy
kivy.require('1.10.0')
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.core.window import Window

SIZE = 2
NUM_BOXES = SIZE * SIZE

class MyGrid(GridLayout):
    def __init__(self, app, matrix, m_size, **kwargs):
        super(MyGrid, self).__init__(**kwargs)
        self.app = app
        self.matrix = matrix
        self.m_size = m_size
        self.sq_size_x = Window.size[0] / m_size
        self.sq_size_y = Window.size[1] / m_size
        self.count = set()

    def on_touch_down(self, touch):
        pass

    def on_touch_move(self, touch):
        try:
            mouse_x, mouse_y = touch.pos
            section_x = int(mouse_x // self.sq_size_x)
            section_y = int(mouse_y // self.sq_size_y)

            self.matrix[section_y][section_x].background_color = (0, 1, 0, 1)

            self.count.add(str(section_y) + "_" + str(section_x))
        except:
            ## DONT KNOW WHY IT GETS OUT OF RANGE SOMETIMES
            pass

        ## FULLY COLORED, CLOSE APP
        if len(self.count) >= NUM_BOXES:
            self.app.stop()

    def on_touch_up(self, touch):
        pass

class MyApp(App):
    def populate_matrix(self):
        matrix = [ [ Button(text="") for x in range(self.m_size) ] for y in range(self.m_size)]
        return matrix

    def populate_layout(self):
        for y in range(self.m_size-1,-1,-1): ## FILL y BACKWARDS, SINCE BOTTOM IS 0
            for x in range(self.m_size):
                self.layout.add_widget(self.matrix[y][x])

    def get_screen_size(self):
        user32 = ctypes.windll.user32
        screensize = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)

        return screensize

    def build(self):
        screensize = self.get_screen_size()
        Window.size = (screensize[0], screensize[1])
        Window.fullscreen = 'auto'  ## MAKES APP FULLSCREEN BUT HAS COORDINATE ISSUES (IF ONLY BYITSELF)
        Window.borderless = True
        self.m_size = SIZE
        self.matrix = self.populate_matrix()
        self.layout = MyGrid(self, self.matrix, self.m_size, cols=self.m_size)
        self.populate_layout()

        return self.layout

if __name__ == "__main__":
    MyApp().run()

touch.spec文件包含以下代码:

# -*- mode: python -*-

block_cipher = None


from kivy_deps import sdl2, glew

a = Analysis(['touch.py'],
             pathex=["C:\\Users\\XXX\\Desktop\\testingKivy"],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='touch',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          runtime_tmpdir=None,
          console=True )

coll = COLLECT(exe, Tree("C:\\Users\\XXX\\Desktop\\testingKivy"),
   a.binaries,
   a.zipfiles,
   a.datas,
   *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
   strip=False,
   upx=True,
   name='touchtracer')

我随后运行了以下命令:

python -m PyInstaller --onefile touch.spec

执行pyinstaller --onefile touch.py时,生成的exe不能正常工作。似乎sld2下的某些依赖项未正确打包。因此,我最终更新了上述的.spec文件。

使用touch.spec文件时,确实会生成单个exe,但该exe本身无法正常工作。在dist文件夹下,它会生成一个touch.exe(本身不起作用),但在dist文件夹下,它还会生成一个名为touchtracer的文件夹,其中有许多文件/dll以及一个可以正常工作的touch.exe。我的问题是,是否有一种方法将所有这些内容打包到一个单独的exe中?

有人说“确保在spec文件中没有收集步骤:

“在单文件模式下,不调用COLLECT,EXE实例接收所有脚本、模块和二进位文件。” (链接)。但我不知道如何用另一种方式包含sdl2依赖项。不确定如何在这种情况下正确使用--add-data。

1个回答

4

使用 .spec 文件参数运行 Pyinstaller 将使其忽略你在命令行中提供的几乎所有选项。 我建议使用 pyi-makespec --onefile touch.py 来获得一个单文件起始的 .spec 文件,然后编辑 touch.spec 文件以添加 sdl 内容。 在 exe 部分的 a.datas 行之后(就像你在 coll 部分中一样),只需添加相同的行 (*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)])。 然后只需运行 python -m PyInstaller touch.spec


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接