Search code examples
pythonwindowstkinterpyinstallerpython-poetry

Cannot locate tkinter icon file when using pyinstaller with poetry on Windows10


I am using this answer to locate my icon file. My project is organised thus

.
│   main.spec
│   poetry.lock
│   pyproject.toml
│   README.md
│
├───my_app
│   │   pyinstaller.py
│   │   __init__.py
│   │
│   └───src
│       │   main.py
│       │
│       └───images
│               icon.png
│
└───dist
        my_app.exe

And my code:

# main.py
import sys
import os
import tkinter as tk
from pathlib import Path

def main() -> None:
    root = tk.Tk()
    icon_file = resolve_path('images/icon.png')
    root.geometry('600x200')
    root.columnconfigure(0, weight=1)
    display_info = tk.StringVar()
    display = tk.Entry(root, textvariable= display_info)
    display.grid(sticky=tk.EW)
    info = f'{Path(icon_file).is_file()} - {icon_file}'
    display_info.set(info)
    # root.iconphoto(False, tk.PhotoImage(file=icon_file))
    root.mainloop()

def resolve_path(path) -> str:
    if getattr(sys, 'frozen', False):
        return os.path.abspath(Path(sys._MEIPASS, path))
    return os.path.abspath(Path(Path(__file__).parent, path))

if __name__ == '__main__':
    main()

The output I get when I run the script is

True - C:\Users\fred\projects\my_app\my_app\src\images\icon.png

But when I build the exe and run that, then output is

False - C:\Users\fred\AppData\Local\Temp\_MEI163682\images\icon.png

So it does not find the file

Where should it be located?


Solution

  • The file needs to be added to the bundle created by pyinstaller.

    To do that you will either need to (i) use the --add-data command, or (ii) add a datas attribute in the Analysis class of your main.spec file.

    A Spec File would look something like this:

    a = Analysis(...
             datas=[ ('src\images\icon.png', 'images') ],
             ...
             )