Kivy: compiling into a single executable file

Failed to get a response on the kivy forum, so try here.

When I compile the training pong code as one executable file, I still have to include the pong.kv file in the same folder in which it runs. Otherwise, when starting exe, the following error occurs:

     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 make it work as a single executable? Here is 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') 

Note that I tried to include pong.kv in the data list, but that did not help.

Thanks, -Raj

+7
python pyinstaller kivy
source share
2 answers

Based on the links provided by KeyWeeUsr ( Linking data files to PyInstaller and Using PyInstaller to make EXE from Python scripts ) and combining this with the Kivy resource path method, here is an executable solution. I feel this is a bit rough around the edges because it uses SYS._MEIPASS (I would prefer a public API) and requires adding a piece of code to your Python code. However, the solution works on both Windows and Mac, so it will share.

Suppose I have the following code hierarchy:

  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 (eg icon file for mac)
        myapp.ico (eg 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 the MyHiddenImports folder to the example if your code also adds another folder containing python code to sys.path at runtime.

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() 

Resource_add_path () tells Kivy where to look for /.vv data files. For example, on a Mac, when starting the pyinstaller application, it pointed to / private / var / folders / 80 / y766cxq10fb_794019j7qgnh0000gn / T / _MEI25602, and on Windows it pointed to c: \ users \ raj \ AppData \ Local \ Temp_MEI64zTut (these folders are deleted after exiting from the application and create a new name at startup again).

I created the source Mac template specification file with the following command:

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

Here's the modified Mac OS specification file:

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

Notes: I added a hidden import path to pathex and referenced the package in hiddenimports. I added the myapp.kv file to the a.datas file, so it will be copied to the application. In the exe, I added a data tree. I included the prefix argument, since I wanted the data folder to be copied to the application (compared to the children sitting at the root level).

To compile the code to create the application and put it in the dmg file, I have a make-myapp script that does the following:

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

Similarly, here are the window specs:

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

And to compile a Windows application:

python -m PyInstaller myapp.spec

+4
source share

If you don't need the length of the code, how about loading kv data inside a .py file using Builder.load_string ? This way all the code is stored inside your python script and can help compile it .exe.

0
source share

All Articles