[Pyinstaller & Ginza] Ginzaを使用したpythonファイルのexe化
日本語の自然言語処理ライブラリであるGinzaを使ったpythonファイルを、pyinstallerでexe化するのにめちゃくちゃハマったので、記事化しました。
Google先生に聞いても解決策がほとんど出てこなかったので需要はないかもしれませんが、もし同じ問題にぶち当たった人がいたときに、その人への一助になれば幸いです。。。
ハマったポイント
pyinstallerでexe化したアプリケーションが動かない
以下、実際出てきたエラー一覧
unhandled exception in script
RuntimeError: Cannot find the MXNet library.
[E053] Could not read config.cfg
tok = dictionary.Dictionary().create(mode=split_mode)
Exception: Error loading config: IO Error: 指定されたパスが見つかりません。 (os error 3)
pyo3_runtime.PanicException: system dictionary hogehoge...\sudachidict_core\resources\system.dic did not exist
原因(だと思われること)
上記みたいなエラーでexeが動かない場合、exe化したいpyファイルから間接参照しているモジュールをpyinstallerが読み込んでくれていない可能性が高いです(例:import spacyをした場合、spacyが参照しているモジュール群)
解決策
下記手順に沿って処理すれば動く・・・はずです
(今回はpyinstallerをGUIで使用できるauto-py-to-exeを使いました)
※下記手順(特に手順2)はこのページを参考にしました。
1. MXNetのインストール(不要な人もいるかも)
MXNetがなかったため、pip install mxnet
2. spacyをちょっと弄る
$python-path\Lib\site-packages\spacy\lang\ja\_init_.pyを一部下記のように編集
def try_sudachi_import(split_mode="A"):
"""SudachiPy is required for Japanese support, so check for it.
It it's not available blow up and explain how to fix it.
split_mode should be one of these values: "A", "B", "C", None->"A"."""
try:
from sudachipy import dictionary, tokenizer
split_mode = {
None: tokenizer.Tokenizer.SplitMode.A,
"A": tokenizer.Tokenizer.SplitMode.A,
"B": tokenizer.Tokenizer.SplitMode.B,
"C": tokenizer.Tokenizer.SplitMode.C,
}[split_mode]
sudachi_config_path = os.path.abspath(os.path.join(os.path.dirname(__file__), r'..\\..\\..\\sudachipy\\resources\\sudachi.json'))
tok = dictionary.Dictionary(config_path=sudachi_config_path).create(mode=split_mode)
return tok
except ImportError:
raise ImportError(
"Japanese support requires SudachiPy and SudachiDict-core "
"(https://github.com/WorksApplications/SudachiPy). "
"Install with `pip install sudachipy sudachidict_core` or "
"install spaCy with `pip install spacy[ja]`."
) from None
sudachi_config_path = os.path.abspath(os.path.join(os.path.dirname(file), r'..\..\..\sudachipy\resources\sudachi.json'))
tok = dictionary.Dictionary(config_path=sudachi_config_path).create(mode=split_mode)
が追記・編集した部分です。
sudachi.jsonのパスは人によって違うかもしれませんが、pip install -U ginza ja-ginzaでginzaを入れた人はこの指定でいけるはずです。
3. pyinstallerのオプションを設定し、exeファイルへコンバート
Onefileオプションを「One directory」に設定し、Advanced内にあるcollect-allに下記を追加し、コンバートを開始します。
- ginza
- ja_ginza
- spacy
- sudachipy
- mxnet
- unidic_lite
4. outputフォルダ内へライブラリを追加
このままだとexeファイルを起動しても、冒頭でお見せしたエラーで止まってしまうため、$python-path\Lib\site-packages\sudachidict_coreを、outputフォルダ内のexeファイルと同じ階層にコピーします。
また、outputフォルダ内のsudachipy内にresourcesがない場合があり、その状態だとまた別のエラーが出てきます。この場合は、site-packages内のsudachipyから、resourcesをフォルダごと上記と同様にコピーしてください。
5. exeファイルの起動
これでエラーなく動作する・・・はずです。これでもまだエラーを吐く場合、collect-allにエラーの原因と思われるモジュールを追加すれば解決するかもしれません。