Have you tried this kind of approach:
Let's assume you have some kind of layout like this
main.py
resources.py
data/img1.png
And in main.py
:
import resources
import tkinter as tk
root = tk.Tk()
root.title("Test")
resources.load_images()
lbl = tk.Label(root, image=resources.IMG1)
lbl.place(relx=0.5, rely=0.5, anchor="c")
root.mainloop()
And in resources.py
:
import tkinter as tk
IMG1 = None
def load_images():
global IMG1
IMG1 = tk.PhotoImage("data\\img1.png")
This works quite nicely, and can load your image.
Now let's make it work in one single exe file:
We don't need to change main.py
, as it simply loads resources through our resources.py
script.
We can load/save our image data using this script:
import base64
def load_data(filename):
with open(filename, mode="rb") as f:
return base64.b64encode(f.read())
print(str(load_data("data\\img1.png"), "utf-8"))
# R0lGOD ...
So we can now copy and paste this into our resources.py
file, and change it to look like this:
import tkinter as tk
# here's our copied base64 stuff:
img1_data = '''
R0lGODlhEAAQALMAAAAAAP//AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA\nAAAAACH5BAEAAAIALAAAAAAQABAAQAQ3UMgpAKC4hm13uJnWgR
TgceZJllw4pd2Xpagq0WfeYrD7\n2i5Yb+aJyVhFHAmnazE/z4tlSq0KIgA7\n
'''
IMG1 = None
def load_images():
global IMG1
IMG1 = tk.PhotoImage(data=img1_data)
And now compile our main.py
file using PyInstaller:
pyinstaller main.py --onefile
And we should see, once the task is complete, that there is a single executable file in dist
, called main.exe
.