Kivy: компиляция в один исполняемый файл

не получил ответа на форуме kivy, поэтому пытаюсь здесь.

когда я компилирую учебник понг код как один исполняемый файл, я должен по-прежнему включать понг.файл кВ в той же папке для его запуска. В противном случае, я получаю следующую ошибку при запуске ехе:


    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:python34libsite-packageskivyapp.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

Как я могу заставить его работать как один исполняемый файл. Вот мой понг.файл спецификации:



    # -*- mode: python -*-

    from kivy.deps import sdl2, glew

    block_cipher = None


    a = Analysis(['Codemain.py'],
                 pathex=['E:DevelopmentPong'],
                 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 += [('Codepong.kv', 'E:DevelopmentPongCodepong.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')

обратите внимание, что я попытался включить понг.кВ в списке данных, но это не помощь.

спасибо, - Радж!--3-->

2 ответов


на основе ссылок, предоставленных KeyWeeUsr (связывание файлов данных с PyInstaller и использование PyInstaller для создания EXEs из скриптов Python) и в сочетании с методом пути к ресурсам Kivy, вот работоспособное решение. Я чувствую, что это немного грубо по краям, потому что он использует SYS._MEIPASS (я бы предпочел публичный 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)

я добавил папку MyHiddenImports в пример, если ваш код также добавляет другую папку, содержащую код python, в sys.путь во время выполнения.

In MyApp.py добавить следующее:

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, где искать данные/.файлы киловольт. Например, на 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=../../ Код / данные / myapp.icns --exclude-module _tkinter -- исключить-модуль Tkinter --исключить-модуль enchant --исключить-модуль 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.данные, поэтому он будет скопирован в приложение. В EXE я добавил дерево данных. Я включил аргумент префикса, поскольку я хотел, чтобы папка данных была скопирована в приложение (против дети сидят на корневом уровне).

чтобы скомпилировать код для создания приложения и поместить его в файл dmg, у меня есть скрипт make-myapp, который делает следующее:

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

аналогично, вот файл спецификации windows:

# -*- 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


Если вас не волнует длина кода, как насчет загрузки данных kv внутри a .py файл с помощью Builder.load_string? Таким образом, весь код хранится внутри вашего скрипта python, и это может помочь скомпилировать его .исполняемый.