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, и это может помочь скомпилировать его .исполняемый.