I am using Python 3.5 and I was able to create an executable using cx_Freeze but whenever I try to run the executable it runs without error but it cannot display any matplotlib figure. I have used Tkinter for my GUI. I have tried putting matplotlib backend as tkinter but figures are still not displaying.I cannot share the whole code as it is huge. Kindly Help.
The following example adapted from the matplotlib
example Embedding In Tk and from the cx_Freeze
sample Tkinter works for my configuration (python 3.6, matplotlib
2.2.2, numpy
1.14.3+mkl, cx_Freeze
5.1.1 on Windows 7).
Main script main.py
:
import tkinterfrom matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figureimport mathroot = tkinter.Tk()
root.wm_title("Embedding in Tk")# Data for plotting
i = range(0, 300)
t = [_i / 100. for _i in i]
s = [2. * math.sin(2. * math.pi * _t) for _t in t]fig = Figure(figsize=(5, 4), dpi=100)
fig.add_subplot(111).plot(t, s)canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)def on_key_press(event):print("you pressed {}".format(event.key))key_press_handler(event, canvas, toolbar)canvas.mpl_connect("key_press_event", on_key_press)def _quit():root.quit() # stops mainlooproot.destroy() # this is necessary on Windows to prevent Fatal Python Error: PyEval_RestoreThread: NULL tstatebutton = tkinter.Button(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)tkinter.mainloop()
# If you put root.destroy() here, it will cause an error if the window is closed with the window manager.
Setup script setup.py
:
import sys
from cx_Freeze import setup, Executable
import os.pathPYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__))
os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')options = {'build_exe': {'include_files': [(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'), os.path.join('lib', 'tk86t.dll')),(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'), os.path.join('lib', 'tcl86t.dll'))],'packages': ['numpy']},
}base = None
if sys.platform == 'win32':base = 'Win32GUI'executables = [Executable('main.py', base=base)
]setup(name='matplotlib_embedding_in_Tkinter',version='0.1',description='Sample cx_Freeze matplotlib embedding in Tkinter script',options=options,executables=executables)
Explanations:
- In order to freeze an application using
Tkinter
with cx_Freeze
, one needs to set the TCL and TK library environment variables in the setup script, and to tell cx_Freeze
to include the corresponding DLLs, see KeyError: 'TCL_Library' when I use cx_Freeze. The solution described there needs to be adapted when using cx_Freeze
5.1.1, see Getting "ImportError: DLL load failed: The specified module could not be found" when using cx_Freeze even with tcl86t.dll and tk86t.dll added in.
numpy
is required by matplotlib
and it needs to be included in the frozen application even if the application itself does not explicitly use numpy
. In order to include numpy
in an application frozen with cx_Freeze
, one needs to add numpy
to the packages
list of the build_exe
option in the setup script, see Creating cx_Freeze exe with Numpy for Python.