Преобразованное cx_freeze GUI-приложение (tkinter) вылетает после нажатия кнопки plot
Я занимаюсь этим уже несколько дней и надеюсь найти помощь. Я разработал GUI-приложение с импортированными модулями tkinter, numpy, scipy, matplotlib, которое отлично работает в самом python. После преобразования в *.exe все работает как положено, но НЕ в разделе matplotlib. Когда я нажимаю свою определенную кнопку plot, *.exe просто закрывается и не показывает никаких графиков. Поэтому я подумал сделать минималистичный пример, где я просто рисую sin-функцию и сталкиваюсь с той же проблемой: прекрасно работает в python, при преобразовании его в *.exe происходит сбой при нажатии кнопки plot. Минималистичный пример здесь:
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()
И посмотрите мой соответствующий "setup.py" для преобразования с помощью 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)
Любые идеи, которые могут решить проблему, высоко ценятся. Я работаю на 64-битной машине с Windows10 и использую дистрибутив WinPython с Python 3.4.3.
3 ответа
Я нашел потенциальное решение (или хотя бы объяснение) для этой проблемы при тестировании PyInstaller с тем же test.py. Я получил сообщение об ошибке отсутствия файла DLL, который является mkl_intel_thread.dll.
Я искал этот файл, и он был найден внутри пустой папки. Я скопировал файлы, соответствующие mkl_*. Dll, а также libiomp5md.dll в ту же директорию, где был создан test.exe, созданный python setup.py build
было. После этого минимальный test.exe показывал окно matplotlib при нажатии кнопки заговора.
Файлы находились в папке lib \ site-packages \ numpy \ core.
Я действительно хотел опубликовать это как комментарий, но у меня нет репутации. В основном это продолжение ответа Дж. Дж. Хакалы о том, как найти причину.
Если изменить базу на "Консоль", то есть используя
base = "Console"
скорее, чем
base = "Win32GUI"
консоль также появится при запуске программы, и эта ошибка выводится
ФАКТИЧЕСКАЯ ОШИБКА Intel MKL: Невозможно загрузить mkl_intel_thread.dll.
Что может помочь найти причину проблемы довольно быстро.
Я думал, что это стоит упомянуть, так как этот прием также может быть полезен для диагностики других проблем. В финальной версии можно вернуться к Win32GUI, чтобы избежать дополнительной консоли. Я должен дать кредиты этому другому сообщению stackru
Я следовал за J.J. Hakala, но обнаружил, что нет необходимости копировать все файлы mkl_*. Dll и libiomp5md.dll. Для меня это работало с libiomp5md.dll mkl_core.dll mkl_def.dll mkl_intel_thread.dll. Это помогает уменьшить окончательный размер пакета в ~500 МБ.
Кроме того, вы можете включить файлы, которые вы хотите скопировать в include_files
вариант. Вы также можете включить их, только если sys.platform
является win32
,
Я использую Anaconda, а также Matt Williams, поэтому немного изменил код 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)
Проверьте, установлен ли у вас пакет numpy+mkl. Удаление numpy и установка пакета numpy+mkl решили мою проблему получения ошибки, связанной с mkl_intel_thread.dll