Convert tkinter to EXE
Question:
Currently, I’m trying to convert my tkinter Python script to an EXE file using cx_freeze. It is somehow not working when I try to add another file. You can see the method I’ve used in the minimum example I’m using below.
import tkinter as tk
import numpy.core._methods, numpy.lib.format
class Main(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.geometry("700x400")
self.wm_iconbitmap('test.ico')
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
frame.update_page() # <-- update data on page when you click button
def get_page(self, page_class):
return self.frames[page_class]
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text="What are the sizes?")
label1.pack()
L1 = tk.Label(self, text="Length :")
L1.pack()
self.E1 = tk.Entry(self)
self.E1.pack()
button = tk.Button(self, text="Next", command=lambda: controller.show_frame(PageOne))
button.pack()
def update_page(self): # empty method but I need it
pass
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text="You have insert")
label1.pack()
# create empty label at start
self.label2 = tk.Label(self, text="")
self.label2.pack()
button = tk.Button(self, text="Back", command=lambda: controller.show_frame(StartPage))
button.pack()
def update_page(self):
# update label when page is changed
page1 = self.controller.get_page(StartPage)
var = page1.E1.get()
self.label2['text'] = var
app = Main()
app.mainloop()
The second script:
import cx_Freeze
import sys
import matplotlib
import os
import numpy.core._methods
import numpy.lib.format
base = None
if sys.platform=='win32':
base = "Win32GUI"
executables = [cx_Freeze.Executable("Show_file.py")]
cx_Freeze.setup(
name = "Name",
options = {
"build_exe": {
"packages": ["tkinter","matplotlib"],
"include_files": ["test.ico"]
}
},
version="0.01",
executables=executables)
It works when I do not add an icon when I try to build the EXE file. However, the EXE does not open anymore when I try to add an icon. Furthermore, when I try to add a database Excel file, I get the message that such a file does not exist. All the files are in the correct folder. That is not the problem.
Answers:
The tkinter runtimes and libraries are missing. To include those I would suggest using os.environ()
and include the runtimes using the include_files
argument as they (briefly) described here.
Using os.environ()
is easy. For example it can be done like this:
os.environ["TCL_LIBRARY"] = "<PathToPython>\Python\Python36-32\tcl\tcl8.6"
os.environ["TK_LIBRARY"] = "<PathToPython>\Python\Python36-32\tcl\tk8.6"
Next include the runtimes (DLLs) in the include files arguement:
options = {"build_exe":{"packages":["tkinter","matplotlib"],"include_files":["test.ico", "<PathToPython>\Python\Python36-32\DLLs\tcl86t.dll", "<PathToPython>\Python\Python36-32\DLLs\tk86t.dll"]}},
Now your whole setup script should look like this:
import sys # Imports are automatically detected (normally) in the script to freeze
import os
base = None
os.environ["TCL_LIBRARY"] = "<PathToPython>\Python\Python36-32\tcl\tcl8.6"
os.environ["TK_LIBRARY"] = "<PathToPython>\Python\Python36-32\tcl\tk8.6"
if sys.platform=='win32':
base = "Win32GUI"
executables = [cx_Freeze.Executable("Show_file.py")]
cx_Freeze.setup(
name = "Name",
options = {"build_exe":{"packages":["tkinter","matplotlib"],"include_files":["test.ico", "<PathToPython>\\Python\Python36-32\DLLs\tcl86t.dll", "<PathToPython>\\Python\Python36-32\DLLs\tk86t.dll"]}},
version="0.01",
executables=executables)
You don’t need all the imports you’re going to use in the setup script, cx_Freeze automatically detects them.
As the title says Converting tkinter to exe
I believe pyinstaller is worth mentioning in this case.
There are some debates on which is better pyinstaller or cx_Freeze on the Internet, but I found pyinstaller
simpler and it worked for me out of the box with tkinter
. A one-liner in cmd:
pyinstaller.exe --onefile --icon=myicon.ico main.py
--onefile
option produces, well, one output file instead of many.
--icon
will connect an icon of your choice.
main.py
is your main file with the main
function.
Currently, I’m trying to convert my tkinter Python script to an EXE file using cx_freeze. It is somehow not working when I try to add another file. You can see the method I’ve used in the minimum example I’m using below.
import tkinter as tk
import numpy.core._methods, numpy.lib.format
class Main(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.geometry("700x400")
self.wm_iconbitmap('test.ico')
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
frame.update_page() # <-- update data on page when you click button
def get_page(self, page_class):
return self.frames[page_class]
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text="What are the sizes?")
label1.pack()
L1 = tk.Label(self, text="Length :")
L1.pack()
self.E1 = tk.Entry(self)
self.E1.pack()
button = tk.Button(self, text="Next", command=lambda: controller.show_frame(PageOne))
button.pack()
def update_page(self): # empty method but I need it
pass
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text="You have insert")
label1.pack()
# create empty label at start
self.label2 = tk.Label(self, text="")
self.label2.pack()
button = tk.Button(self, text="Back", command=lambda: controller.show_frame(StartPage))
button.pack()
def update_page(self):
# update label when page is changed
page1 = self.controller.get_page(StartPage)
var = page1.E1.get()
self.label2['text'] = var
app = Main()
app.mainloop()
The second script:
import cx_Freeze
import sys
import matplotlib
import os
import numpy.core._methods
import numpy.lib.format
base = None
if sys.platform=='win32':
base = "Win32GUI"
executables = [cx_Freeze.Executable("Show_file.py")]
cx_Freeze.setup(
name = "Name",
options = {
"build_exe": {
"packages": ["tkinter","matplotlib"],
"include_files": ["test.ico"]
}
},
version="0.01",
executables=executables)
It works when I do not add an icon when I try to build the EXE file. However, the EXE does not open anymore when I try to add an icon. Furthermore, when I try to add a database Excel file, I get the message that such a file does not exist. All the files are in the correct folder. That is not the problem.
The tkinter runtimes and libraries are missing. To include those I would suggest using os.environ()
and include the runtimes using the include_files
argument as they (briefly) described here.
Using os.environ()
is easy. For example it can be done like this:
os.environ["TCL_LIBRARY"] = "<PathToPython>\Python\Python36-32\tcl\tcl8.6"
os.environ["TK_LIBRARY"] = "<PathToPython>\Python\Python36-32\tcl\tk8.6"
Next include the runtimes (DLLs) in the include files arguement:
options = {"build_exe":{"packages":["tkinter","matplotlib"],"include_files":["test.ico", "<PathToPython>\Python\Python36-32\DLLs\tcl86t.dll", "<PathToPython>\Python\Python36-32\DLLs\tk86t.dll"]}},
Now your whole setup script should look like this:
import sys # Imports are automatically detected (normally) in the script to freeze
import os
base = None
os.environ["TCL_LIBRARY"] = "<PathToPython>\Python\Python36-32\tcl\tcl8.6"
os.environ["TK_LIBRARY"] = "<PathToPython>\Python\Python36-32\tcl\tk8.6"
if sys.platform=='win32':
base = "Win32GUI"
executables = [cx_Freeze.Executable("Show_file.py")]
cx_Freeze.setup(
name = "Name",
options = {"build_exe":{"packages":["tkinter","matplotlib"],"include_files":["test.ico", "<PathToPython>\\Python\Python36-32\DLLs\tcl86t.dll", "<PathToPython>\\Python\Python36-32\DLLs\tk86t.dll"]}},
version="0.01",
executables=executables)
You don’t need all the imports you’re going to use in the setup script, cx_Freeze automatically detects them.
As the title says Converting tkinter to exe
I believe pyinstaller is worth mentioning in this case.
There are some debates on which is better pyinstaller or cx_Freeze on the Internet, but I found pyinstaller
simpler and it worked for me out of the box with tkinter
. A one-liner in cmd:
pyinstaller.exe --onefile --icon=myicon.ico main.py
--onefile
option produces, well, one output file instead of many.
--icon
will connect an icon of your choice.
main.py
is your main file with the main
function.