1

I've seen some related questions here and tried every single solution I found like this and this for example, but I couldn't make that work. So the question is simple - after making single exe file from kivy it throws a FileNotFoundError: [Errno 2] No such file or directory: 'main2.kv'. Exe file with related files works good but I don't know what am I doing wrong while building single exe.

My spec file:

# -*- mode: python ; coding: utf-8 -*-

from kivymd.tools.packaging.pyinstaller import hooks_path as kivymd_hooks_path
from kivy_deps import sdl2, glew
...
a = Analysis(['main.py'],
    ...
    # I tried to write here absolute path, relative path and this method
    datas=[('*.kv', '.')],
    hiddenimports=[],
    hookspath=[kivymd_hooks_path],
    ...
)

# I also tried to put import here - didn't help (when I did that I also tried to change the path in my .py file to 'Data\main2.kv')
# a.datas += [('main2.kv', 'D:\\prog\\Lotto\\main2.kv', 'DATA')]
...

# tried with Tree and without Tree
coll = COLLECT(exe, Tree('D:\\prog\\Lotto','Data'),
    ...
    *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
    ...

In .py file I tried to add

if getattr(sys, 'frozen', False):
    kivy.resources.resource_add_path(sys._MEIPASS)

And

def resourcePath():
    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())
    MainApp().run()

And tried both of above methods together - nothing. Also tried to change PyInstaller 3.6 to 3.5 version. I don't know what's the problem here, it's my first time trying to make exe file from Kivy.

Lothric
  • 1,283
  • 2
  • 6
  • 11

1 Answers1

1

Few hours later finally I got that. I open my kv file as file first and then pass it to Builder to be able to set the encoding. In that case I just needed to define the path of kv file manually as sys._MEIPASS + 'main2.kv' and then it worked.

UPD: To make that work make few imports first:

import os, sys
from kivy.resources import resource_add_path

and then at the end of your app just before MainApp.run() add this:

if __name__ == "__main__":
    # these lines should be added
    if hasattr(sys, '_MEIPASS'):
        resource_add_path(os.path.join(sys._MEIPASS))
    ###
    MainApp().run()

When we build single .exe file it holds all files inside of it, so it unpacks it to some random temporary folder while running. sys._MEIPASS here is the path of that temp folder.

So that should work. If it still can't find files, you can try to change file path like this: for example, instead of 'example.kv' write sys._MEIPASS + '/' + 'example.kv'.

Also make sure you've done everything right in the .spec file, so you should add your files to datas list in Analysis like this:

        a = Analysis(['main.py'],
             ...
             datas=[('main.kv', '.'), ('bg.png', '.'), ('CenturyGothic.ttf', '.'), ('finish.mp3', '.'), ('Logo.png', '.'),],

So if you have only kv file to add it would be:

datas=[('main.kv', '.')],
Lothric
  • 1,283
  • 2
  • 6
  • 11
  • Thank you! This got me into the right direction. An additional thing I had to fix with my code: `Builder.load_file("some_file.kv")` can only be called after `resource_add_path(os.path.join(sys._MEIPASS))` – Lucas Mar 20 '22 at 12:13