ToxicGLaDOS
ToxicGLaDOS

Reputation: 483

Pyinstaller doesn't play well with ImageTk and Tkinter

I'm trying to use pyinstaller to make builds of a program I've been developing but I'm running into problems with the binary afterward. Here has been my procedure.

First I ran pyinstall test.py Then I ran the binary using ./dist/main/test but I get this error which I don't get when running the script normally (such as python3 test.py).

Traceback (most recent call last):
  File "PIL/ImageTk.py", line 181, in paste
_tkinter.TclError: invalid command name "PyImagingPhoto"

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "magic-collection-tracker/test.py", line 22, in <module>
  File "magic-collection-tracker/test.py", line 11, in main
  File "PIL/ImageTk.py", line 120, in __init__
  File "PIL/ImageTk.py", line 185, in paste
ModuleNotFoundError: No module named 'PIL._tkinter_finder'

Here is a minimal example that reproduces the issue.

from PIL import ImageTk
import PIL.Image
from tkinter import *



window = Tk()
pil_img = PIL.Image.open('./scr_images/blank_card.png')
tkimage = ImageTk.PhotoImage(pil_img)
canvas = Canvas(window)
canvas.create_image(0,0,image=tkimage, anchor=NW)
canvas.pack()

window.mainloop()

Am I using pyinstaller incorrectly or is there some other problem?

Upvotes: 3

Views: 2691

Answers (2)

fresbeeplayer
fresbeeplayer

Reputation: 103

I'm 2 months late now, but to add a simpler solution I managed to get it working adding a couple of hidden imports:

hiddenimports=['PIL', 'PIL._imagingtk', 'PIL._tkinter_finder']

Upvotes: 8

BoobyTrap
BoobyTrap

Reputation: 978

I know this is over a month old but I found myself struggling with this as well as it didn't seem to want to work in any of the suggested ways.
Seeing as other people might get stuck with this in the future, here is how I used an hotfix for this.
Once you create an executable using PyInstaller for the first time, a spec file is created.
This file looks something like this (for --onefile):

a = Analysis(['main_file.py'],
             pathex=['/root/folder'],
             binaries=[],
             datas=[],
             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='app_name',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          runtime_tmpdir=None,
          console=True )

What I did was simply copy PIL into the file using datas in this manner:

datas=[('/usr/local/lib/python3.7/dist-packages/PIL/','PIL'),],

Now everything is working as it should, until I find a better solution when I have the time.

Keep in mind that the spec file will be overwritten if PyInstaller will be used on main_file.py(in this case). Instead, pyinstaller main_file.spec should be used.

Upvotes: 1

Related Questions