python - Kivy:编译为单个可执行文件

标签 python kivy pyinstaller

在 kivy 论坛上没有得到回复,所以在这里尝试。

当我将教程 pong 代码编译为一个文件可执行文件时,我仍然必须将 pong.kv 文件包含在同一文件夹中才能运行。 否则,启动 exe 时会出现以下错误:


    GL: EXT_framebuffer_object is supported
    [INFO              ] [GL          ] OpenGL version 
    [INFO              ] [GL          ] OpenGL vendor 
    [INFO              ] [GL          ] OpenGL renderer 
    [INFO              ] [GL          ] OpenGL parsed version: 2, 1
    [INFO              ] [GL          ] Shading version 
    [INFO              ] [GL          ] Texture max size 
    [INFO              ] [GL          ] Texture max units 
    [INFO              ] [Window      ] auto add sdl2 input provider
    [INFO              ] [Window      ] virtual keyboard not allowed,
    single mode, not docked
     Traceback (most recent call last):
       File "", line 81, in 
       File "c:\python34\lib\site-packages\kivy\app.py", line 802, in
    run
         root = self.build()
       File "", line 75, in build
       File "", line 20, in serveBall
     AttributeError: 'NoneType' object has no attribute 'center'
    main returned -1

How can I get it to run as one executable. Here's my pong.spec file:



    # -*- mode: python -*-

    from kivy.deps import sdl2, glew

    block_cipher = None


    a = Analysis(['Code\main.py'],
                 pathex=['E:\\Development\\Pong'],
                 binaries=None,
                 datas=None,
                 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)

    a.datas += [('Code\pong.kv', 'E:\\Development\\Pong\Code\pong.kv', 'DATA')] 

    exe = EXE(pyz,Tree('Code'),
              a.scripts,
              a.binaries,
              a.zipfiles,
              a.datas,
              *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
              name='pong',
              debug=False,
              strip=False,
              upx=True,
              console=True , icon='pong.ico')

请注意,我尝试将 pong.kv 包含在数据列表中,但这没有帮助。

谢谢, -拉吉

最佳答案

基于 KeyWeeUsr(Bundling data files with PyInstallerUsing PyInstaller to make EXEs from Python scripts)提供的链接,并结合 Kivy 的资源路径方法,这是一个可行的解决方案。我觉得它的边缘有点粗糙,因为它使用 SYS._MEIPASS(我更喜欢公共(public) API)并且需要将代码片段添加到您的 Python 代码中。但是,该解决方案适用于 Windows 和 Mac,因此将共享。

假设我有以下代码层次结构:

MyCode/
    MyApp.py  (This is the main program)
    myapp.kv  (This is the associated kv file)

    MyData/      (This is where data is located that the app uses)
       myapp.icns (e.g. icon file for mac)
       myapp.ico  (e.g. icon file for windows)

Build/
    mac/ 
        myapp.spec (spec file to build on mac platform)
    pc/ 
        myapp.spec (spec file to build on windows platform)

MyHiddenImports/ (Folder containing python files for hidden imports)

I added a MyHiddenImports folder to the example in case your code also appends another folder containing python code to sys.path during run time.

In MyApp.py add the following:

def resourcePath():
    '''Returns path containing content - either locally or in pyinstaller tmp file'''
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS)

    return os.path.join(os.path.abspath("."))

if __name__ == '__main__':
    kivy.resources.resource_add_path(resourcePath()) # add this line
    my_app = MyApp()

resources_add_path() 告诉 Kivy 去哪里寻找 data/.kv 文件。例如,在 Mac 上,当运行 pyinstaller 应用程序时,它指向/private/var/folders/80/y766cxq10fb_794019j7qgnh0000gn/T/_MEI25602,在 Windows 中,它指向 c:\users\raj\AppData\Local\Temp_MEI64zTut (这些文件夹在退出应用程序后被删除,并在再次启动时创建另一个名称)。

我使用以下命令创建了初始 Mac 模板规范文件:

pyinstaller --onefile -y --clean --windowed --name myapp --icon=../../Code/Data/myapp.icns --exclude-module _tkinter --exclude-module Tkinter --exclude-module enchant --exclude-module twisted ../../Code/MyApp.py

这是修改后的 Mac OS 规范文件:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['../../Code/MyApp.py'],
            pathex=['/Users/raj/Development/Build/mac', 
            '../../MyHiddenImports'],    
            binaries=None,
            datas=None,
            hiddenimports=['MyHiddenImports'],    
            hookspath=[],
            runtime_hooks=[],
            excludes=['_tkinter', 'Tkinter', 'enchant', 'twisted'],
            win_no_prefer_redirects=False,
            win_private_assemblies=False,
            cipher=block_cipher)

pyz = PYZ(a.pure, a.zipped_data,
            cipher=block_cipher)

a.datas += [('myapp.kv', '../../MyCode/my.kv', 'DATA')]

exe = EXE(pyz, Tree('../../Code/Data', 'Data'), 
            a.scripts,
            a.binaries,
            a.zipfiles,
            a.datas,
            name='myapp',
            debug=False,
            strip=False,
            upx=True,
            console=False , icon='../../Code/Data/myapp.icns')

app = BUNDLE(exe,
             name='myapp.app',
             icon='../../Code/Data/myapp.icns',
             bundle_identifier=None)

注意事项:我在pathex中添加了隐藏导入路径,并在hiddenimports中引用了包。我将 myapp.kv 文件附加到 a.datas,以便将其复制到应用程序中。在 EXE 中,我添加了数据树。我包含了前缀参数,因为我希望将 Data 文件夹复制到应用程序中(而不是让子项位于根级别)。

要编译代码以创建应用程序并将其放入 dmg 文件中,我有一个执行以下操作的 make-myapp 脚本:

pyinstaller -y --clean --windowed myapp.spec
pushd dist
hdiutil create ./myapp.dmg -srcfolder myapp.app -ov
popd
cp ./dist/myapp.dmg .

Similarly, here's the windows spec file:

# -*- mode: python -*-

from kivy.deps import sdl2, glew

block_cipher = None


a = Analysis(['..\\..\\Code\\Cobbler.py'],
             pathex=['E:\\Development\\MyApp\\Build\\pc',
             '..\\..\\MyHiddenImports'],
             binaries=None,
             datas=None,
             hiddenimports=['MyHiddenImports'],
             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)

a.datas += [('myapp.kv', '../../Code/myapp.kv', 'DATA')]

exe = EXE(pyz, Tree('..\\..\\Code\\Data','Data'),
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
          name='myapp',
          debug=False,
          strip=False,
          upx=True,
          console=False, icon='..\\..\\Code\\Data\\myapp.ico' )

并编译 Windows 应用程序:

python -m PyInstaller myapp.spec

关于python - Kivy:编译为单个可执行文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35952595/

相关文章:

python - 将 period_range 转换为字符串列表

python - 将 CSV 从 AWS S3 实例导入到 Numpy

python - 如何删除 kivy 中的小部件?

python - pyinstaller生成的exe文件在其他计算机上有延迟

python - 由于 Win32 模块,PyInstaller 无法正常工作

python - 使用 emacs 将 python 文档字符串突出显示为注释

Python:将二维数组沿不同的行插入到 3D NumPy 数组中

scrollview - 设置 kivy scrollview effects_cls 属性的正确方法是什么?

python - 如何在python的kivy应用程序模块中更改屏幕背景的颜色?

python - 检测 python 程序是否通过 Windows GUI(双击)与命令提示符执行