1

I was creating a tkinter program which I need to make into exe so I can send it to my friends. so for this program, I needed to add a .png and .ico file. Here is the code I typed in pyinstaller to install the exe

pyinstaller .\u.py -F --noconsole --add-data 'C:\Users\Binoy\Desktop\Techwiz\h.png; .' -i ".\h.ico"

This is my .spec file:

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

block_cipher = None


a = Analysis(['U.py'],
             pathex=['C:\\Users\\Binoy\\Desktop\\New folder'],
             binaries=[],
             datas=[('C:\\Users\\Binoy\\Desktop\\Techwiz\\h.png', '.')],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='U',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=False , icon='h.ico')

I also got a .txt file regaridng missing modules but in the .txt,they said that these modules won't affect the .exe so I didn't care about it.At first it was running without any problem but then if I delete the .png or if one of my friends download it,it shows the error Failed to execute script U. so I tried the resource_path() function (Pyinstaller and --onefile: How to include an image in the exe file),but didn't work. So I created a .bat file (Keep error message of exe file which is created by Pyinstaller),and got this error:

Traceback (most recent call last):
File "U.py", line 19, in <module>
File "tkinter\__init__.py", line 4062, in __init__
File "tkinter\__init__.py", line 4007, in __init__
_tkinter.TclError: couldn't open "C:/Users/Binoy/Desktop/Techwiz/h.png": no such file or directory
[8736] Failed to execute script U

Is there any way to store images(.png) with the .exe file as a single .exe file?

Code2D
  • 119
  • 1
  • 14
  • 3
    i think you have hard coded the file reference in your python program. easy way is keep .py and image at same level so you can just put the file name when reading it. – simpleApp Apr 30 '21 at 02:08
  • 2
    you are trying to load that file in your py ... nothing to do with bundling ...your just not giving it the right path (your code is indeed already including the file in the binary (with datas) .... it expands it to a randomly named temp folder where im sure you can find the file ... you need to use the resource path ... but depending on version of pyinstaller its `sys._MEIPASS` or `os.environ['MEIPASS2']` – Joran Beasley Apr 30 '21 at 02:26

1 Answers1

1

Joran Beasley is right with his comment. You may have some issues with your path setup. If I want to want to compile an executable, that has also extern files included, I use the following approach

from PIL import Image
import os
import sys

#check if its a compiled exe
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
    filePath = os.path.join(sys._MEIPASS, "test_picture.png")
#otherwise it must be a script 
else:
    scriptPath = os.path.realpath(os.path.dirname(sys.argv[0]))
    filePath = os.path.join(scriptPath, "test_picture.png")

f = Image.open(filePath).show() 

In this example, the 'test_picture' will be relative to the script, if a run it as a .py file. Otherwise, it will be stored in the temporary _MEI folder. Latter one is defined via

datas = [...]

which you already did in your spec file.

Also, if you run a pyinstaller executable, you may want to check the following path.

C:\Users...\AppData\Local\Temp\

There should be a folder, called _MEI followed by some numbers. This is the folder where your executable will be extracted, as well as all the data you included

See also

https://pyinstaller.readthedocs.io/en/stable/runtime-information.html

What is sys._MEIPASS in Python

stranger0612
  • 301
  • 1
  • 2
  • 12
  • I did try what u said and also made the script you typed into exe.but however it shows this error: `File "imgfinder.py", line 13, in File "PIL\Image.py", line 2904, in open FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\Binoy\\Desktop\\Techwiz\\h.png' [7720] Failed to execute script imgfinder` – Code2D Apr 30 '21 at 11:23
  • Here is the script in imgfinder.py: `from PIL import Image import os import sys #check if its a compiled exe if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'): filePath = os.path.join(sys._MEIPASS, r"C:\Users\Binoy\Desktop\Techwiz\h.png") #otherwise it must be a script else: scriptPath = os.path.realpath(os.path.dirname(sys.argv[0])) filePath = os.path.join(scriptPath, r"C:\Users\Binoy\Desktop\Techwiz\h.png") f = Image.open(filePath).show()` – Code2D Apr 30 '21 at 11:24
  • is there any other solution @Marcel.S – Code2D Apr 30 '21 at 11:29
  • 1
    Change this os.path.join(sys._MEIPASS, r"C:\Users\Binoy\Desktop\Techwiz\h.png") to simply this os.path.join(sys._MEIPASS, "h.png"). You have to understand how pyinstaller handles included data. As i tried to explain, the file you include will be extracted on runtime to the _MEIPASS folder. So the .exe will use the filepath C:\Users...\AppData\Local\Temp\_MEIXXX\h.png. – stranger0612 Apr 30 '21 at 11:29
  • 1
    Other solution would the approach of @simpleApp. Keep it all relative to each other. My tipp for such implementations: Try to keep all relative to each other and avoid hardcoded absolute paths – stranger0612 Apr 30 '21 at 11:31
  • thanks,it is working.Maybe next time ,I have to be careful to notice these.once again thanks to all who gave their solutions – Code2D Apr 30 '21 at 11:37