Table Of Contents
Create a package for Windows¶
Note
This document only applies for kivy 1.9.1
and greater.
Packaging your application for the Windows platform can only be done inside the Windows OS. The following process has been tested on Windows with the Kivy wheels installation, see at the end for alternate installations.
The package will be either 32 or 64 bits depending on which version of Python you ran it with.
Requirements¶
- Latest Kivy (installed as described in Installation on Windows).
- PyInstaller 3.1+ (
pip install --upgrade pyinstaller
).
PyInstaller default hook¶
Warning
The latest PyInstaller release does not include the Kivy hooks. This note will be removed when a PyInstaller version with the hooks is released to PyPi.
This section applies to PyInstaller (>= 3.?) that includes the kivy hooks. For previous versions of PyInstaller or to overwrite the default hook the following examples need to be slightly modified. See Overwriting the default hook for those changes.
Packaging a simple app¶
For this example, we’ll package the touchtracer example project and embed a custom icon.
The location of the kivy examples is, when using the wheels, installed to python\\share\\kivy-examples
and when using the github source code installed as kivy\\examples
. We’ll just refer to the full
path leading to the examples as examples-path
. The touchtracer example is in
examples-path\\demo\\touchtracer
and the main file is named main.py
.
Open your command line shell and ensure that python is on the path (i.e.
python
works).Create a folder into which the packaged app will be created. For example create a
TouchApp
folder and change to that directory with e.g.cd TouchApp
. Then type:python -m PyInstaller --name touchtracer examples-path\demo\touchtracer\main.py
You can also add an icon.ico file to the application folder in order to create an icon for the executable. If you don’t have a .ico file available, you can convert your icon.png file to ico using the web app ConvertICO. Save the icon.ico in the touchtracer directory and type:
python -m PyInstaller --name touchtracer --icon examples-path\demo\touchtracer\icon.ico examples-path\demo\touchtracer\main.py
For more options, please consult the PyInstaller Manual.
The spec file will be
touchtracer.spec
located inTouchApp
. Now we need to edit the spec file to add the dependencies hooks to correctly build the exe. Open the spec file with your favorite editor and add these lines at the beginning of the spec (assuming sdl2 is used, the default now):from kivy.deps import sdl2, glew
Then, find
COLLECT()
and add the data for touchtracer (touchtracer.kv, particle.png, ...): Change the line to add aTree()
object, e.g.Tree('examples-path\\demo\\touchtracer\\')
. This Tree will search and add every file found in the touchtracer directory to your final package.To add the dependencies, before the first keyword argument in COLLECT add a Tree object for every path of the dependecies. E.g.
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)]
so it’ll look something like:coll = COLLECT(exe, Tree('examples-path\\demo\\touchtracer\\'), a.binaries, a.zipfiles, a.datas, *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)], strip=False, upx=True, name='touchtracer')
Now we build the spec file in
TouchApp
with:python -m PyInstaller touchtracer.spec
The compiled package will be in the TouchApp\dist\touchtracer directory.
Packaging a video app with gstreamer¶
Following we’ll slightly modify the example above to package a app that uses gstreamer
for video. We’ll use the videoplayer
example found at examples-path\widgets\videoplayer.py
.
Create a folder somewhere called VideoPlayer
and on the command line change your current
directory to that folder and do:
python -m PyInstaller --name gstvideo examples-path\widgets\videoplayer.py
to create the gstvideo.spec
file. Edit as above and this time include the
gstreamer dependency as well:
from kivy.deps import sdl2, glew, gstreamer
and add the Tree()
to include the video files, e.g. Tree('examples-path\\widgets')
as well as the gstreamer dependencies so it should look something like:
coll = COLLECT(exe, Tree('examples-path\\widgets'),
a.binaries,
a.zipfiles,
a.datas,
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins + gstreamer.dep_bins)],
strip=False,
upx=True,
name='gstvideo')
Then build the spec file in VideoPlayer
with:
python -m PyInstaller gstvideo.spec
and you should find gstvideo.exe in VideoPlayer\dist\gstvideo
,
which when run will play a video.
Note
If you’re using Pygame and need PyGame in your packaging app, you’ll have to add the following code to your spec file due to kivy issue #1638. After the imports add the following:
def getResource(identifier, *args, **kwargs):
if identifier == 'pygame_icon.tiff':
raise IOError()
return _original_getResource(identifier, *args, **kwargs)
import pygame.pkgdata
_original_getResource = pygame.pkgdata.getResource
pygame.pkgdata.getResource = getResource
Overwriting the default hook¶
Including/excluding video and audio and reducing app size¶
PyInstaller includes a hook for kivy that by default adds all the core modules
used by kivy, e.g. audio, video, spelling etc (you still need to package
the gstreamer dlls manually with Tree()
- see the example above) and their
dependencies. If the hook is not installed or to reduce app size some of these
modules may be excluded, e.g. if no audio/video is used, with a alternative hook.
Kivy provides the alternate hook at
hookspath()
. In addition, if and only
if PyInstaller doesn’t have the default hooks
runtime_hooks()
must also be provided.
When overwriting the hook, the latter one typically is not required to be overwritten.
The alternate hookspath()
hook
does not include any of the kivy providers. To add them, they have to be added with
get_deps_minimal()
or
get_deps_all()
. See
their documentation and pyinstaller_hooks
for more
details. But essentially, get_deps_all()
add all the providers like in the default hook while
get_deps_minimal()
only adds those
that are loaded when the app is run. Each method provides a list of hidden kivy imports
and excluded imports that can be passed on to Analysis
.
One can also generate a alternate hook which literally lists every kivy provider
module and those not required can be commented out. See
pyinstaller_hooks
.
To use the the alternate hooks with the examples above modify as following to
add the hooks with hookspath()
and runtime_hooks
(if required)
and **get_deps_minimal()
or **get_deps_all()
to specify the providers.
For example, add the import statement
from kivy.tools.packaging.pyinstaller_hooks import get_deps_minimal,
get_deps_all, hookspath, runtime_hooks
and then modify Analysis
as follows:
a = Analysis(['examples-path\\demo\\touchtracer\\main.py'],
...
hookspath=hookspath(),
runtime_hooks=runtime_hooks(),
...
**get_deps_all())
to include everything like the default hook. Or:
a = Analysis(['examples-path\\demo\\touchtracer\\main.py'],
...
hookspath=hookspath(),
runtime_hooks=runtime_hooks(),
...
**get_deps_minimal(video=None, audio=None))
e.g. to exclude the audio and video providers and for the other core modules only use those loaded.
The key points is to provide the alternate
hookspath()
which does not list
by default all the kivy providers and instead manually to hiddenimports
add the required providers while removing the undesired ones (audio and
video in this example) with
get_deps_minimal()
.
Alternate installations¶
The previous examples used e.g.
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins + gstreamer.dep_bins)],
to make PyInstaller add all the dlls used by these dependencies. If kivy
was not installed using the wheels method these commands will not work and e.g.
kivy.deps.sdl2
will fail to import. Instead, one must find the location
of these dlls and manually pass them to the Tree
class in a similar fashion
as the example.