Trouble with Kivy when trying to compile Python file (+.kv file) into a "One File" executable

262 views
Skip to first unread message

ITDSS

unread,
Nov 20, 2018, 9:02:12 AM11/20/18
to Kivy users support
Hello,

I am an IT internee, and have a project I work on. This project consists of Python code. With this project I also use Kivy with it for the stylisation of the buttons (as I have a GUI). I want to compile this code to a One File exe though, but it gives me problems relating to Kivy. I have attached an image with the error I get when I try to open the compiled exe. I also make use of an external library, which I had problems with earlier, but this works now. Now the problem lies within the Kivy files (I have one .kv file, and a couple of images). I have no idea what to do.

I'd greatly appreciate any help.

Kind regards,

ITDSS

PS: If there are any questions, ask away, so I can clear up any uncertainties/misunderstandings!
error.png

Elliot Garbus

unread,
Nov 20, 2018, 9:37:23 AM11/20/18
to Kivy users support
I assume you are using pyinstaller.  
IF you have any external files, you need to tell pyinstaller about them in the spec file, and you need to make some minor changes to your code.  The location of external files will be different if your python is 'frozen'.  See: https://pythonhosted.org/PyInstaller/spec-files.html#adding-data-files

In the spec file you would need to add something like:
a = Analysis(...
     datas=[ ('src/README.txt', '.') ],
     ...
     )

Where you replace 'src/README.txt' with the name of your image file.
In your python code you need to tell python if you are froze (running from the .exe) or not, see this example from the pyinstaller docs:
import sys, os
frozen = 'not'
if getattr(sys, 'frozen', False):
        # we are running in a bundle
        frozen = 'ever so'
        bundle_dir = sys._MEIPASS
else:
        # we are running in a normal Python environment
        bundle_dir = os.path.dirname(os.path.abspath(__file__))
print( 'we are',frozen,'frozen')
print( 'bundle dir is', bundle_dir )
print( 'sys.argv[0] is', sys.argv[0] )
print( 'sys.executable is', sys.executable )
print( 'os.getcwd is', os.getcwd() )

You need to join the bundle directory with the name of your file, so your program can access it frozen or not frozen.

I'll find an example later today and post it.

ITDSS

unread,
Nov 21, 2018, 8:54:01 AM11/21/18
to Kivy users support
Hello,

I use a simplified version of Pyinstaller: autopy (It is basically Pyinstaller with a simple GUI).

I have put every needed file (images, .kv, external library files) basically in the root when I tried to compile.
I have attached an image with my compiled folder structure, so you can see what I mean.

It just states that it has that error as displayed in my earlier attachment.

I hope this attached image will help.

Kind regards,

ITDSS
folder structure.JPG

Elliot Garbus

unread,
Nov 21, 2018, 10:05:24 AM11/21/18
to Kivy users support
I suggest sticking with PyInstaller.  Go with  a one directory build.  Given the number of files in a kivy project, it will not build into one file.  It will be a multifie output even if a single file is requested.
Follow the directions to the letter for doing a build as in the kivy packaging directions.  Create a separate directory as specified.   It will be easier to help you if you share your .spec file.

Here is the code where I pull in my icon and KV file, this is under build(), and requires import sys, os (at the top of the file.


if getattr(sys, 'frozen', False): # required so data files can be packed by pyinstaller
application_path = sys._MEIPASS
else:
application_path = os.path.dirname(__file__)
iconfile = os.path.join(application_path, 'SY300logo64.png')
kvfile = os.path.join(application_path, 'osc_panel.kv')
self.icon = iconfile
r = Builder.load_file(kvfile)

This lets lets the program know where these data files are when it is 'frozen'.  I'm not completely certain this is required, but i have done this in a recent kivy project and it worked fine. This is described in the PyInstaller documentation.

Here is the PyInstaller specfile for my project:

# -*- mode: python -*-
from kivy.deps import sdl2, glew
block_cipher = None


a = Analysis(['..\\main.py'],
             pathex=['C:\\Users\\Elliot and Sharon\\PycharmProjects\\sand_box\\try'],
             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,
          [],
          exclude_binaries=True,
          name='try',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe, Tree('C:\\Users\\Elliot and Sharon\\PycharmProjects\\sand_box\\'),
               a.binaries,
               a.zipfiles,
               a.datas,
               *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
               strip=False,
               upx=True,
               name='try')

ITDSS

Elliot Garbus

unread,
Nov 21, 2018, 8:06:18 PM11/21/18
to Kivy users support
I did a test and found that this code was NOT required.
   
if getattr(sys, 'frozen', False): # required so data files can be packed by pyinstaller application_path = sys._MEIPASS else: application_path = os.path.dirname(__file__) iconfile = os.path.join(application_path, 'SY300logo64.png') kvfile = os.path.join(application_path, 'osc_panel.kv')

Hope you're making progress!
Reply all
Reply to author
Forward
0 new messages