Sam
Sam

Reputation: 25

Image won't load for tkinter program compiled with pyinstaller

I have a tkinter program that includes a .png image. I have compiled it using pyinstaller and the --onefile option so I have to access the image in a temporary location. This is the code I am using:

def resource_path(relative_path):
    try:
        base_path = sys._MEIPASS
    except Exception as e:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)
title = PhotoImage(file=resource_path("xgol.png"))

Here is my .spec file:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['XGols.py'],
             pathex=['C:\\Users\\Sam\\OneDrive\\Computing\\Python Projects\\FootballPredict'],
             binaries=[],
             datas=[('Ball.ico', 'Ball.ico'), ('xgol.png', 'xgol.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='XGols',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          runtime_tmpdir=None,
          console=True , icon='Ball.ico')

To compile the program I use:

pyinstaller --onefile XGols.spec

This is the error that I get when I run the executable

_tkinter.TclError: couldn't open "C:\Users\Sam\AppData\Local\Temp\_MEI61842\xgol.png": permission denied

I have tried running as administrator.

Upvotes: 1

Views: 413

Answers (2)

Morteza Parkook
Morteza Parkook

Reputation: 21

If file not found error: Use MEIPASS2 instead of MEIPASS or vise versa and then \ instead of / if needed.

I think this way is a lot easier:

import os
import sys

def resource_path(relative_path):
    try:
        base_path = sys._MEIPASS # after running the pyinstaller, if still looking
        # for temp folder then use sys._MEIPASS2 and if needed \\ instead of / for
        # all the path directories
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

Replace the

"folder_names/file_names" 

with

resource_path("file_names/file_names")

in the Terminal type:

pyinstaller.exe --onefile --windowed  --icon=your_image.ico Your_File.py

or in windows CMD (after installing the pyinstaller in cmd) type:

pyinstaller --onefile --windowed --icon=your_image.ico Your_File.py

The executable file will be available in a new folder called "dist".

now copy all the dependent folders into the "dist" folder

run the .exe and if all fine then zip the folder to share.

Delete Build and Dist folder along with any .spec files.

Replace the

resource_path("folder_names/file_names") 

back to

"folder_names/file_names"

To go one step further and turn it into a setup installer file, use "inno setup" software.

Upvotes: 1

john-hen
john-hen

Reputation: 4866

In your .spec file, additional data files should be listed like so:

datas=[('Ball.ico', '.'), ('xgol.png', '.')]

From the documentation:

Each tuple has two values, both of which must be strings:

  • The first string specifies the file or files as they are in this system now.
  • The second specifies the name of the folder to contain the files at run-time.

Upvotes: 2

Related Questions