Googleのクライアントライブラリをimportしているプログラムをpyinstallerで.exe化する


Google Speech to Textを使ったプログラムを.exe化する必要があったのだが、ハマったのでメモ。

環境

OS Windows10
(pipenvにて)
Python 3.7.4
pyinstaller 3.6

実行したコマンド

test.pyを.exe化する。と仮定すると、

pyinstaller test.py --onefile

ERROR1

まず、普通に実行すると以下のようなエラーが出る

pkg_resources.DistributionNotFound: The 'google-cloud-core' distribution was not found and is required by the application

このエラーに関しては起動時に--additional-hooks-dirオプションを使用して、以下のようなファイルを作成し、フォルダへのパスを与えれば解決する。というような記事をよく見かけるが、自分の環境では解決しなかった。

hook-google.cloud.py
from PyInstaller.utils.hooks import copy_metadata
try:    datas = copy_metadata('google-cloud-core')
except: datas = copy_metadata('google-cloud-speech')

↓このエラーが出る

    assert self.hook_module_name not in HOOKS_MODULE_NAMES
AssertionError

この問題に関しては普通に、google-cloud-coreを改めてインストールすると解決した。。。

pip install google-cloud-core

ERROR2

google-cloud-coreをインストールしたあとは、実行出来て.exeも生成されるのだが、生成された.exeを実行すると今度は以下のようなエラー(というかException?)が出る。

Exception ignored in: 'grpc._cython.cygrpc.ssl_roots_override_callback'
E0603 18:31:14.600000000 16632 src/core/lib/security/security_connector/ssl_utils.cc:482] assertion failed: pem_root_certs != nullptr

ライセンスの認証周りっぽい。
こちらは、test.pyと同階層にhooksというフォルダを作成し、その中に以下にようなファイルを作成して設置したとすると、

hook-grpc.py
from PyInstaller.utils.hooks import collect_data_files
datas = collect_data_files('grpc')

以下のようなコマンドでビルドしなおせば出なくなる

pyinstaller test.py --onefile --additional-hooks-dir=./hooks/

参考

https://github.com/pyinstaller/pyinstaller/issues/3935
https://teratail.com/questions/201443
https://teratail.com/questions/118297
https://qiita.com/akitooo/items/eb82a5f335d8ca9c9faf
https://stackoverflow.com/questions/54634035/my-pyinstaller-is-giving-assertion-error-when-i-execute-it
https://stackoverflow.com/questions/40076795/pyinstaller-file-fails-to-execute-script-distributionnotfound
https://www.bountysource.com/issues/86848733-pyinstaller-3-6-assertionerror
https://github.com/googleapis/google-cloud-python/issues/5774