PyTorchで記述したPythonスクリプトをPyInstallerでexe化


環境

・Windows 10 pro 64bit
・Python 3.7.9
・Anaconda 4.8.5
・PyTorch 1.6.0+cpu
・Pyinstaller 4.0

はじめに

Pythonスクリプトをexe化する場合に、よく使われるものとして、Pyinstallerというものがあります。ここでは、PyTorchで文書分類器を作ったスクリプトをexe化したときに、起こったエラーの対処方法を記載していきます。

Anacondaを使っている人へ

ライブラリのインストールは、pipcondaが混在しないようにしてください。また、exe化する際は、exe化するスクリプトに必要なライブラリのみをインストールした仮想環境を作ることをおすすめします。仮想環境の作り方は以下の通りです。

以下のPyTorchのフォーラムにpipでインストールするようにと書かれていましたので、私は全てpipでインストールしました。

Create exe file - PyTorch Forums

Pyinstallerの使い方

インストール

$ pip install pyinstaller

通常はexe化したいスクリプトのあるディレクトリで、以下のコマンド1つでexeファイルにできます。(exeファイル1つにしたい場合は--onefileを後ろに付ける)

$ pyinstaller sample.py

今回は、specファイルを編集したのとonefileではなかなかうまく実行できなかったで、以下の2つの手順でexeファイルにしていきます。

まず、以下のコマンドでspecファイルを作ります。

$ pyi-makespec sample.py --onedir

次に以下のコマンドexeファイルを作ります。

$ pyinstaller sample.spec --clean

--cleanは、同じスクリプトに関してpyinstallerで作られたファイルを削除するオプションです。build内にデータがなければ付ける必要はありません。
このコマンドを実行したディレクトリにbuilddistというディレクトリが作られているはずです。dist内にexeファイルが作られています。

PyTorchに関するエラー

exeファイル実行時に以下のようなエラーが発生しました。

File "torch\__init__.py", line 189, in <module>
ImportError: numpy.core.multiarray failed to import

exe化したいpythonスクリプトに以下の文を追加し、multiarrayを明示的にインポートすることで解決しました。

import numpy.core.multiarray

dllファイルが見つからないエラーまたは警告

lib not found: 〇〇.dll

pyi-makespecまたはpyinstallerでexe化する際に、〇〇.specのようなファイルが作られていると思います。そのファイルのa=Analysisのpathex部分を以下のように修正します。

sample.spec
a = Analysis(['sample.py'],
             pathex=['exe化するファイルのパス', 'エラーが出ていたdllファイルがあるディレクトリのパス(追加)'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)

私の場合、torch_python.dllでしたので、'エラーが出ていたdllファイルがあるディレクトリのパス(追加)'は以下のようなパスになります。(releaseという仮想環境で作業を行っている場合)
'C:\ProgramData\Anaconda3\envs\release\Lib\site-packages\torch\lib'

※specファイルを修正したので、exeファイルを作る際はpyinstaller sample.pyではなく以下のようにしてください。

$ pyinstaller sample.spec --clean

Janomeに関するエラー

形態素解析器にJanomeを使っていると実行時に以下のようなエラーが出ると思います。

FileNotFoundError: [Errno 2] No such file or directory: 
'C:\\Users\\username\\AppData\\Local\\Temp\\_MEI172322\\janome\\sysdic\\entries_compact0.py'

ファイルのパスは人によって微妙に違います。onefileオプションを付けている人は、同じようなパスになっていると思います。

Janomeで使っている辞書データをpyinstallerが認識してくれず組み込めないことが原因らしいです。exeがあるディレクトリにjanomeをフォルダごとコピーしておきましょう。janomeの中にあるsysdic以外は消しても問題ありません。

私の場合は以下のようなパスにjanomeのフォルダがありました。
C:\ProgramData\Anaconda3\envs\release\Lib\site-packages\janome

以下の記事でエラーの原因が書かれていました。
パワポエンジニアの憂鬱を軽減する誤字/表記揺れ検出ツールを作った物語

transformersに関するエラー

huggingfaceのtransformersのtokenizerを使っていた場合、実行時に以下のようなエラーが出ると思います。

FileNotFoundError: [Errno 2] No such file or directory: 
'C:\\Users\\username\\AppData\\Local\\Temp\\_MEI191522\\sacremoses\\data\\perluniprops\\IsN.txt'

こちらも、Janomeに関するエラーと同じで、tokenizerで用いる辞書データをpyinstallerが認識してくれず組み込めないことが原因です。janomeと対処方法は同じでexeのあるディレクトリにsacremosesをフォルダごとコピーすれば解決です。sacremoses内のdata\perluniprops以外は消しても問題ありません。
私の場合のsacremosesのパスは以下の通りです。
C:\ProgramData\Anaconda3\envs\release\Lib\site-packages\sacremoses

最後に

Pyinstallerを使っていると原因がよくわからないエラーが出たりします。原因が調べてもわからなかった場合は、警告文に対処していくのも1つの方法です。私もそのようにしていました 調べても出てこなかったときは、諦めかけていたのですが、なんとかなるもんですね。Pyinstaller自体の開発も現在進行形で続いているので、将来のアップデートで解決されるかもしれませんね。

参考

Create exe file - PyTorch Forums
https://discuss.pytorch.org/t/create-exe-file/56626

パワポエンジニアの憂鬱を軽減する誤字/表記揺れ検出ツールを作った物語
https://qiita.com/youwht/items/062c41c88829fcf25107