La aplicación GUI convertida cx_freeze (tkinter) se bloquea después de presionar plot-Button

He estado lidiando con esto por días y espero encontrar ayuda. Desarrollé una aplicación GUI con módulos importados tkinter, numpy, scipy, matplotlib, que funciona bien en Python. Después de haber convertido a un * .exe todo funciona como se esperaba, pero NO la sección matplotlib. Cuando presiono mi botón de trazado definido, el * .exe simplemente se cierra y no muestra ningún gráfico. Así que pensé en hacer un ejemplo minimalista, donde simplemente trazo una función de pecado y me enfrento al mismo problema: Funciona perfectamente en Python, al convertirlo en un * .exe se bloquea al presionar el botón de trazado. El ejemplo minimalista está aquí:

import tkinter as tk import matplotlib.pyplot as plt import numpy as np class MainWindow(tk.Frame): def __init__(self): tk.Frame.__init__(self,bg='#9C9C9C',relief="flat", bd=10) self.place(width=x,height=y) self.create_widgets() def function(self): datax = np.arange(-50,50,0.1) datay = np.sin(datax) plt.plot(datax,datay) plt.show() def create_widgets(self): plot = tk.Button(self, text='PLOT', command=self.function) plot.pack() x,y=120,300 root=tk.Tk() root.geometry(str(x)+"x"+str(y)) app = MainWindow() app.mainloop() 

Y vea mi “setup.py” correspondiente para convertir con cx_freeze.

 import cx_Freeze import matplotlib import sys import numpy import tkinter base = None if sys.platform == "win32": base = "Win32GUI" executables = [cx_Freeze.Executable("test.py", base=base)] build_exe_options = {"includes": ["matplotlib.backends.backend_tkagg","matplotlib.pyplot", "tkinter.filedialog","numpy"], "include_files":[(matplotlib.get_data_path(), "mpl-data")], "excludes":[], } cx_Freeze.setup( name = "test it", options = {"build_exe": build_exe_options}, version = "1.0", description = "I test it", executables = executables) 

Cualquier idea que pueda resolver el problema es muy apreciada. Estoy trabajando en una máquina Windows10 de 64 bits y estoy usando la distribución WinPython con Python 3.4.3.

Encontré una solución potencial (o al menos una explicación) para este problema mientras probaba PyInstaller con el mismo test.py. Recibí un mensaje de error sobre la falta de un archivo dll, ese archivo es mkl_intel_thread.dll .

Busqué ese archivo y lo encontré dentro de la carpeta numpy . Copié archivos que coincidían con mkl _ *. Dll y también libiomp5md.dll en el mismo directorio donde estaba el test.exe creado por python setup.py build . Después de esto, el archivo minimal test.exe mostró la ventana matplotlib al presionar el botón de trazado .

Los archivos se encontraban en la carpeta lib \ site-packages \ numpy \ core .

Tenía muchas ganas de publicar esto como un comentario, pero no tengo la reputación. Esto es principalmente un seguimiento de la respuesta de JJ Hakala sobre cómo encontrar la causa.

Si uno cambia la base a “Consola”, es decir, usando

  base = "Consola" 

más bien que

  base = "Win32GUI" 

También se abrirá una consola cuando se inicie el progtwig y se imprima este error.

  Intel MKL FATAL ERROR: No se puede cargar mkl_intel_thread.dll. 

Lo que puede ayudar a encontrar la causa del problema bastante más rápido.

Pensé que valdría la pena mencionarlo, ya que este truco también puede ser útil para diagnosticar otros problemas. En la versión final, uno puede volver a Win32GUI para evitar la consola adicional. Debería dar los créditos a esta otra publicación de stackoverflow.

He seguido la respuesta de @JJ Hakala , pero descubrí que no es necesario copiar todos los archivos mkl _ *. Dll y libiomp5md.dll. Para mí, funcionó con libiomp5md.dll mkl_core.dll mkl_def.dll mkl_intel_thread.dll. Esto ayuda a reducir el tamaño del paquete final en ~ 500MB.

Además, puede incluir los archivos que desea copiar en la opción include_files . También es posible que solo desee incluirlos si sys.platform es win32 .

Estoy usando Anaconda así como @Matt Williams , así que, cambiando un poco el código del OP:

 import cx_Freeze import matplotlib import sys import numpy import tkinter import os PYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__)) build_exe_options = {"includes": ["matplotlib.backends.backend_tkagg","matplotlib.pyplot", "tkinter.filedialog","numpy"], "include_files":[(matplotlib.get_data_path(), "mpl-data")], "excludes":[], } base = None if sys.platform == "win32": base = "Win32GUI" DLLS_FOLDER = os.path.join(PYTHON_INSTALL_DIR, 'Library', 'bin') dependencies = ['libiomp5md.dll', 'mkl_core.dll', 'mkl_def.dll', 'mkl_intel_thread.dll'] for dependency in dependencies: build_exe_options['include_files'].append(os.path.join(DLLS_FOLDER, dependency)) executables = [cx_Freeze.Executable("test.py", base=base)] cx_Freeze.setup( name = "test it", options = {"build_exe": build_exe_options}, version = "1.0", description = "I test it", executables = executables) 

Compruebe si tiene instalado el paquete numpy + mkl. Desinstalar numpy e instalar el paquete numpy + mkl solucionó mi problema de obtener un error relacionado con mkl_intel_thread.dll