I have a simple kivy file in which i want to cover the entire canvas with an image bgi.jpg
MainWidget:
<MainWidget>:canvas.before:Rectangle:size:self.sizesource:'bgi.jpg'
and the .py file code is
from kivy.app import App
from kivy.uix.widget import Widget
class MainWidget(Widget):pass
class TestApp(App):pass
TestApp().run()
I tried to build this code into .exe file using auot-py-to-exe.
i added both kivy file and the image file as a additional file and tried to build into exe but the executable file is crashing with the error as shown below
Traceback (most recent call last):File "kivy\lang\builder.py", line 925, in _build_canvasFile "kivy\graphics\instructions.pyx", line 380, in kivy.graphics.instructions.VertexInstruction.source.__set__File "kivy\graphics\context_instructions.pyx", line 431, in kivy.graphics.context_instructions.BindTexture.source.__set__File "kivy\core\image\__init__.py", line 561, in __init__File "kivy\core\image\__init__.py", line 754, in _set_filenameFile "kivy\core\image\__init__.py", line 460, in loadFile "kivy\core\image\__init__.py", line 223, in __init__File "kivy\core\image\img_sdl2.py", line 47, in load
Exception: SDL2: Unable to load imageDuring handling of the above exception, another exception occurred:Traceback (most recent call last):File "Main.py", line 9, in <module>File "kivy\app.py", line 954, in runFile "kivy\app.py", line 923, in _run_prepareFile "kivy\app.py", line 696, in load_kvFile "kivy\lang\builder.py", line 305, in load_fileFile "kivy\lang\builder.py", line 405, in load_stringFile "kivy\uix\widget.py", line 470, in apply_class_lang_rulesFile "kivy\lang\builder.py", line 540, in applyFile "kivy\lang\builder.py", line 595, in _apply_ruleFile "kivy\lang\builder.py", line 928, in _build_canvaskivy.lang.builder.BuilderException: Parser: File "C:\Users\User\Documents\Python scripts\Python class\Kivy projects\exe test\Main with image\test.kv", line 6:...4: Rectangle:5: size:self.size>> 6: source:'bgi.jpg'7: Label:8: id:lbl...Exception: SDL2: Unable to load imageFile "kivy\lang\builder.py", line 925, in _build_canvasFile "kivy\graphics\instructions.pyx", line 380, in kivy.graphics.instructions.VertexInstruction.source.__set__File "kivy\graphics\context_instructions.pyx", line 431, in kivy.graphics.context_instructions.BindTexture.source.__set__File "kivy\core\image\__init__.py", line 561, in __init__File "kivy\core\image\__init__.py", line 754, in _set_filenameFile "kivy\core\image\__init__.py", line 460, in loadFile "kivy\core\image\__init__.py", line 223, in __init__File "kivy\core\image\img_sdl2.py", line 47, in load
I am fairly new to both kivy,python and pyinstaller, so i have no idea what is wrong or should image files be added in a different method
auto-py-to-exe is not able to create exe file from Kivy project. It's a GUI for PyInstaller with limitations which won't allow you make required modifications to generate proper exe file.
In general you should follow the Kivy documentation: https://kivy.org/doc/stable/guide/packaging-windows.html and use pure PyInstaller .
But in my opinion the amount of provided informations/scenarios may be overwhelming, so here is my tutorial:
Add following lines to your main python script (usually main.py), on top of file:
import os, sysif sys.__stdout__ is None or sys.__stderr__ is None:os.environ['KIVY_NO_CONSOLELOG'] = '1'from kivy.resources import resource_add_path, resource_findif hasattr(sys, '_MEIPASS'):resource_add_path(os.path.join(sys._MEIPASS))
Download PyInstaller package
pip install pyinstaller
Currently latest PyInstaller version is 5.7.0, you can specify it if you want to:
pip install pyinstaller==5.7.0
Create PyInstaller spec file
pyi-makespec --noconsole --onefile --name "main" --add-data="*.kv;." --add-data="*.jpg;." "main.py"
Notes:
- noconsole will remove console window- onefile will create all-in-one exe file- name specify spec and final exe file name- add-data will include specified file/files into exe. You can use wildcards here like *.jpg- last param is your main Python script file name
pyi-makespec will create following "main.spec" file:
# -*- mode: python ; coding: utf-8 -*-block_cipher = Nonea = Analysis(['main.py'],pathex=[],binaries=[],datas=[('*.kv', '.'), ('*.jpg', '.')],hiddenimports=[],hookspath=[],hooksconfig={},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,a.binaries,a.zipfiles,a.datas,[],name='main',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,upx_exclude=[],runtime_tmpdir=None,console=False,disable_windowed_traceback=False,argv_emulation=False,target_arch=None,codesign_identity=None,entitlements_file=None,)
PyInstaller spec file is in fact Python script. You have to modify it to be able to build proper exe for Kivy based project.
If you decide for example to enable console, you don't have to generate new spec file using pyi-makespec command. Just modify already generated spec file, which contain all parameters you passed to pyi-makespec first time. It's easy to match pyi-makespec arguments within "main.spec" file content. For instance if you want to enable console, then you have to change "console=False," to "console=True,". If you want to add another file to exe, like "image.png", just change "datas=[('.kv', '.'), ('.jpg', '.')]," to "datas=[('.kv', '.'), ('.jpg', '.'), ('image.png', '.')],". If you want to change final exe name from "main.exe" to "my_app.exe" just change "name='main'," to "name='my_app',".
But if you want to create one-folder with binaries instead of all-in-one exe file, you have to use pyi-makespec command again, and remove "--onefile" argument. The spec file for onefile and onefolder is slightly different.
Add Kivy specific lines to "main.spec" file
Compared to original spec file two lines are added:
from kivy_deps import sdl2, glew, gstreamer # Kivy imports*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)], # Kivy binaries
Here is modified "main.spec" file:
# -*- mode: python ; coding: utf-8 -*-from kivy_deps import sdl2, glew, gstreamer # Kivy importsblock_cipher = Nonea = Analysis(['main.py'],pathex=[],binaries=[],datas=[('*.kv', '.'), ('*.jpg', '.')],hiddenimports=[],hookspath=[],hooksconfig={},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,a.binaries,a.zipfiles,a.datas,*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)], # Kivy binaries excluding gstreamer.dep_bins[],name='main',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,upx_exclude=[],runtime_tmpdir=None,console=False,disable_windowed_traceback=False,argv_emulation=False,target_arch=None,codesign_identity=None,entitlements_file=None,)
Please keep in mind, that "Kivy binaries" line is added under "a.datas," line. It's new line, and it have to be placed here.
If your app will use video content played by gstreamer, you will have to modify line:
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
to
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins + gstreamer.dep_bins)],
In result your exe file size may be bigger.
You can read about different scenarios on https://kivy.org/doc/stable/guide/packaging-windows.html
Create exe file
pyinstaller --clean "main.spec"
It will create "build" and "dist" folders. First one is a temporary folder used by PyInstaller to collect required files. Within second one you will find your generated exe file (main.exe).
If you remove "--clean" argument next build attempts will be faster, because PyInstaller will not collect required packages again. But if you for example uninstall some packages using "pip uninstall" because you decide to not use it anymore in your project, the exe size will not decrease, as long previously collected dependencies will be still stored in your exe file. To execute collect step again just keep "--clean" argument.
That's all. auto-py-to-exe is not able to include required lines into spec file, as it hides generated spec file from users's eyes.
Produced exe file is standalone. There is no need to install Python or any Python package on end user PC to run such exe file.
Python interpreter with all dependencies are included into this exe. When exe is started all content is silently unpacked to temporary folder, and folder is removed when app is closed properly.