8

I have made a program with python 3.7 using tkinter aswell. Since I am using external pictures I need to include them when I compile everything to one exe. I have tried doing --add-data "bg.png;files" but I still get this error:

_tkinter.TclError: couldn't open "files/bg.png": no such file or directory

Here is the code:

image = PhotoImage(file="files/bg.png")
w = image.width()
h = image.height()
x = 316
y = 246
mainGui.geometry("%dx%d+%d+%d" % (w, h, x, y))
panel = Label(mainGui, image=image)
panel.pack(side='top', fill='both', expand='yes')

What am I doing wrong? I have tried --add-binary as well, adding the file to my spec file. Seriously can't figure this out!

Kamal
  • 2,384
  • 1
  • 13
  • 25
Michael L
  • 163
  • 1
  • 1
  • 8
  • Maybe [this recipe](https://github.com/pyinstaller/pyinstaller/wiki/Recipe-Collect-Data-Files) is useful? – Edgar Ramírez Mondragón Dec 03 '18 at 04:22
  • 1. Which OS are you using? 2. Are you using -F or --one-file option when compiling with pyinstaller? – Kamal Dec 03 '18 at 04:59
  • Hi Kamal, I am running Windows 10. I have tried both -F and --one-file. – Michael L Dec 03 '18 at 05:40
  • Please try once without -F or --one-file option. For --one-file option, you need to follow add code like [this](https://stackoverflow.com/a/13790741/5319738) – Kamal Dec 03 '18 at 06:39
  • Same thing unfortunately :/ – Michael L Dec 03 '18 at 07:12
  • The files do get included, I can see the size getting larger when I tell pyinstaller to include them. But for some reason my actual program can't find them! – Michael L Dec 03 '18 at 07:13
  • Please share your code as per guidelines here https://stackoverflow.com/help/mcve – Kamal Dec 03 '18 at 07:23
  • Here is the code from my python script where I call my file: `image = PhotoImage(file="files/bg.png")` `w = image.width()` `h = image.height()` `x = 316` `y = 246` `mainGui.geometry("%dx%d+%d+%d" % (w, h, x, y))` `panel = Label(mainGui, image=image)` `panel.pack(side='top', fill='both', expand='yes')` It is located in the same directory as the script, so when I run it in PyCharm it all works like it should. But when I compile it in pyinstaller, with or without -F or --onefile, it doesnt find it – Michael L Dec 03 '18 at 19:20

1 Answers1

20

Sorry, I thought that only -F/--one-file makes such behavior, but looks like any bundling with pyinstaller needs such changes.

You need to change your code like this, as explained in this answer:

import sys

if getattr(sys, 'frozen', False):
    image = PhotoImage(file=os.path.join(sys._MEIPASS, "files/bg.png"))
else:
    image = PhotoImage(file="files/bg.png")

And then bundle it with pyinstaller like this:

pyinstaller --clean -y -n "output_name" --add-data="files\bg.png;files" script.py
Kamal
  • 2,384
  • 1
  • 13
  • 25
  • 1
    You are a legend, thank you soooo much! Works flawless! – Michael L Dec 04 '18 at 04:28
  • Just a small update. I have some sound aswell and I tried adapting those lines into my winsound.Playsound, but it doesn't seem to take it the same way as tkinter does. winsound.PlaySound(os.path.join(sys._MEIPASS, "files/bgm.wav", winsound.SND_LOOP + winsound.SND_ASYNC)) Do you know how to formulate it so python understand it? @Kamal Don't really understand how I can use the 'code' function here on stackoverflow, so it hope its possible to read it. – Michael L Dec 04 '18 at 04:44
  • You have closed the parenthesis of `os.path.join` at wrong position, try: `winsound.PlaySound(os.path.join(sys._MEIPASS, "files/bgm.wav"), winsound.SND_LOOP+winsound.SND_ASYNC)`. And check [here](https://meta.stackexchange.com/questions/77485/code-formating-in-comments) for formatting help. – Kamal Dec 04 '18 at 04:56
  • That did it, thanks for all the help @Kamal! I started programming a week ago, feels good to learn new stuff all the time! – Michael L Dec 04 '18 at 05:25
  • Stumbled here by chance, but this solved my problem: "How to make the Python script auto-determine if it's running in the regular interpreter (i.e. *script.py*) or from a package created with PyInstaller (*script.exe*)? I actually discovered that the *frozen* attribute is set to True in the .exe version, while in the .py it is == False. Thank you so much! – Max1234-ITA Mar 28 '23 at 14:36