web-dev-qa-db-ja.com

プロットボタンを押すと、cx_Freeze変換されたGUIアプリ(tkinter)がクラッシュする

私はこれに何日も取り組んできましたが、助けを見つけたいと思っています。インポートされたモジュールtkinter、numpy、scipy、matplotlibを使用してGUIアプリケーションを開発しました。これは、python自体で正常に実行されます。exeに変換した後は、すべてが期待どおりに機能しますが、matplotlibセクションは機能しません。定義したプロットボタンを押すと、exeが閉じてプロットが表示されないので、最小限の例を作成しようと思いました。ここでは、sin関数をプロットするだけで、同じ問題に直面しています。Pythonで完全に機能します。 、それをexeに変換するとき、プロットボタンを押すとクラッシュします。最小の例を次に示します。

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で使用しています。

10
PuseMuckeL

同じtest.pyでPyInstallerをテストしているときに、この問題の潜在的な解決策(または少なくとも説明)を見つけました。 dllファイルが見つからないというエラーメッセージが表示されました。そのファイルはmkl_intel_thread.dllです。

そのファイルを検索したところ、numpyフォルダー内で見つかりました。 mkl _ *。dllおよびlibiomp5md.dllに一致するファイルを、python setup.py buildによって作成されたtest.exeと同じディレクトリにコピーしました。だった。この後、最小のtest.exeは、plotボタンを押したときにmatplotlibウィンドウを表示しました。

ファイルはフォルダlib\site-packages\numpy\coreにありました。

31
J.J. Hakala

本当にコメントとして投稿したかったのですが、評判がよくありません。これは主にJ.J.のフォローアップです。原因を見つける方法についてのハカラの答え。

ベースを「コンソール」に変更した場合、つまり

base = "コンソール"

のではなく

base = "Win32GUI"

プログラムの起動時にコンソールもポップアップし、このエラーが出力されます

Intel MKL致命的エラー:mkl_intel_thread.dllをロードできません。

これは、問題の原因をかなり早く見つけるのに役立ちます。

このトリックは他の問題の診断にも役立つ可能性があるため、これは言及する価値があると思いました。最終リリースでは、余分なコンソールを回避するためにWin32GUIに戻すことができます。私はこの他の人にクレジットを与える必要があります stackoverflow post

5
Hashimoto

@J.J。Hakala の回答に従いましたが、すべてのmkl _ *。dllファイルとlibiomp5md.dllファイルをコピーする必要はないことがわかりました。私にとっては、libiomp5md.dll mkl_core.dll mkl_def.dllmkl_intel_thread.dllで動作しました。これにより、最終的なバンドルサイズを最大500MBに削減できます。

また、コピーするファイルをinclude_filesオプションに含めることができます。また、sys.platformwin32の場合にのみそれらを含めることもできます。

私は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)
2
javrd

Numpy + mklパッケージがインストールされているかどうかを確認してください。 numpyをアンインストールしてnumpy + mklパッケージをインストールすると、mkl_intel_thread.dllに関連するエラーが発生するという問題が解決しました。

0
arun babu