19

Does anybody know a way to embed an icon in a Python script such that when I create my standalone executable (using pyinstaller) I don't need to include the .ico file? I know this is possible with py2exe, but in my case I have to use Pyinstaller, as I was not successful using the former. I am using Tkinter.

I know about iconbitmap(iconName.ico) but that doesn't work if I wanna make a onefile executable.

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
maupertius
  • 1,518
  • 4
  • 17
  • 30
  • Just to make it clearer: I want to change the icon of my application window (which by default has the Tk logo), not the icon of my file (which can be easily done with Pyinstaller) – maupertius Mar 30 '12 at 13:12
  • Aha! After googling a bit more I found an answer on Stack Overflow [here](http://stackoverflow.com/a/7675014/404469). Does that help? – gary Mar 30 '12 at 14:26
  • Yeah I've seen that one before. It's exactly my same problem. I just don't understand what he does there. It does look like it's the correct solution, maybe I should dig a bit more. Thanks! – maupertius Mar 30 '12 at 14:35

5 Answers5

25

Actually the function iconbitmap can only receive a filename as argument, so there needs to be a file there. You can make a Base64 version of the icon (A string version) following the link, uploading the file and copying the result in your source file as a variable string. Extract it to a temporal file, finally passing that file to iconbitmap and deleting it. It's quite simple:

import base64
import os
from Tkinter import *
##The Base64 icon version as a string
icon = \
""" REPLACE THIS WITH YOUR BASE64 VERSION OF THE ICON
"""
icondata= base64.b64decode(icon)
## The temp file is icon.ico
tempFile= "icon.ico"
iconfile= open(tempFile,"wb")
## Extract the icon
iconfile.write(icondata)
iconfile.close()
root = Tk()
root.wm_iconbitmap(tempFile)
## Delete the tempfile
os.remove(tempFile)

Hope it helps!

Saúl Pilatowsky-Cameo
  • 1,224
  • 1
  • 15
  • 20
  • Thanks a lot, that worked beautifully! Do you by any chance know how to change the icon in a figure window created with Matplotlib? My application has got my icon now, but when I plot the graph, the new window still has the TK logo as icon. Many thinks for your help – maupertius Apr 17 '12 at 10:32
  • Sorry, I don't know about Matplotlib, but if there is not a function for changing the icon, I don't think there is a way. Doesn't wm_iconbitmap work in Matplotlib? – Saúl Pilatowsky-Cameo Apr 18 '12 at 03:18
13

You probably don't need this but somebody else might find this useful, I found you can do it without creating a file:

import Tkinter as tk

icon = """
    REPLACE THIS WITH YOUR BASE64 VERSION OF THE ICON
    """

root = tk.Tk()
img = tk.PhotoImage(data=icon)
root.tk.call('wm', 'iconphoto', root._w, img)
freakrho
  • 545
  • 1
  • 5
  • 13
  • I actually wasn't able to get this method or Sam's method to work with an icon in Python 3.4.3 but Saulpila's method worked so I know there wasn't any error with the Base64 code. – Tony Apr 21 '15 at 05:29
5

Solution by ALI3N

Follow these steps:

  1. Edit your .spec file like this:
a = Analysis(....)
pyz = PYZ(a.pure)
exe = EXE(pyz,
          a.scripts,
          a.binaries + [('your.ico', 'path_to_your.ico', 'DATA')], 
          a.zipfiles,
          a.datas, 
          name=....
       )
  1. Add this to your script:
datafile = "your.ico" 
if not hasattr(sys, "frozen"):
    datafile = os.path.join(os.path.dirname(__file__), datafile) 
else:  
    datafile = os.path.join(sys.prefix, datafile)
  1. Use it this way:
root = tk.Tk()
root.iconbitmap(default=datafile)

Because this wont work after You compile your script with Pyinstaller:

root = tk.Tk()
root.iconbitmap(default="path/to/your.ico")

My Info: python3.4, pyinstaller3.1.1

Community
  • 1
  • 1
ALI3N
  • 302
  • 4
  • 10
  • Im getting error: SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape – alienware13user Apr 16 '17 at 22:05
  • 1
    For me, the solution was to use relative path for `path_to_your.ico` instead of absolute path and it's working like a charm. – May.D Feb 08 '19 at 10:43
2

This worked for me:

from tkinter import  PhotoImage
import base64
img = """
REPLACE THIS WITH YOUR BASE64 VERSION OF THE ICON
"""
img= base64.b64decode(img)

root = Tk()
img=PhotoImage(data=img) 
root.wm_iconphoto(True, img)
D V
  • 139
  • 1
  • 3
  • 10
1
import Tkinter as tk

icon = """
REPLACE THIS WITH YOUR BASE64 VERSION OF THE ICON
"""

root = tk.Tk() 
root.iconphoto(True, PhotoImage(data=icon))

Convert a .png file instead of an icon, also using utf-8 encoding with the same code above worked great for me!

Jessie Wilson
  • 69
  • 2
  • 7