Search code examples
pythonkivypyinstaller

Kivy: PyInstaller add additional files


How to add additional files into the dist-folder during a compilation (python -m PyInstaller tlum.spec)?

I've added them to datas, but it's not helping

a = Analysis(
    ['..\\src\\main.py'],
    pathex=[],
    binaries=[],
    datas=[
        ("..\\assets\\data\\dictionary.txt","assets\\data"),
        ("..\\assets\\images\\error.png","assets\\images"),
        ("..\\assets\\images\\success.png","assets\\images"),
        ("..\\src\\component\\harmonica_widget.py","component"),
        ("..\\src\\template\\game_harmonica.kv","template"),
        ("..\\src\\template\\game_parrot.kv","template"),
        ("..\\src\\template\\game_phonetics.kv","template"),
        ("..\\src\\template\\main.kv","template"),
    ],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
    optimize=0,
)

Failing with an error:

Traceback (most recent call last):
  File "main.py", line 71, in <module>
  File "kivy\app.py", line 955, in run
  File "kivy\app.py", line 925, in _run_prepare
  File "main.py", line 32, in build
  File "kivy\lang\builder.py", line 308, in load_file
FileNotFoundError: [Errno 2] No such file or directory: 'template/main.kv'

Only when I add needed folders/files into the dist folder, everything works.

enter image description here

Sources: https://github.com/lyskouski/app-language/blob/main/windows/tlum.spec


Solution

  • In my codes that may be run through pyinstaller, I use kivy.resources.resource_find() to access data files. And I adjust the kivy resources path like this at the start of my main python script:

    import kivy.resources
    
    if getattr(sys, 'frozen', False):
        # this is a Pyinstaller bundle
        kivy.resources.resource_add_path(sys._MEIPASS)
        kivy.resources.resource_add_path(os.path.join(sys._MEIPASS, 'dialogs'))
    

    Adding all the folders where my data files are stored. And this can be used as:

    kvPath = kivy.resources.resource_find('gamescreen.kv')
    

    Then the kivy.resources.resource_find() will work whether it is in a pyinstaller bundle or not.