はじめに
ときどき以下のすべてを満たしたいというご要望をいただくことがあります。
- Pythonで作ったAIをWindowsアプリに組み込みたい
- AIのインターフェースはWeb APIにしたい
- リモートサーバと通信したくない
- 運用端末にはPythonをインストールしたくない
色々やり方はあると思いますが、
- AIの機能をPythonのWebフレームワークでWeb APIとして公開できるようにし、
- そのPythonスクリプトをEXEファイルに変換してアプリ本体に同梱し、
- アプリ本体からEXEを実行すればこれを実現できます。
今回は以下を使います。
- OS:Windows 10
- Python:3.7.7 (開発環境にのみインストール)
- Webフレームワーク:Flask
- EXE化:PyInstaller
(ちなみにFastAPI × uvicornだと、2020/3/30時点では問題がありました。 https://github.com/pyinstaller/pyinstaller/pull/4664 )
手順
FlaskとPyInstallerをインストールします。
コマンドプロンプトなどで、
pip install flask pyinstaller
Web APIを公開するPythonファイルを作ります。
from flask import Flask
app = Flask(__name__)
@app.route('/predict')
def predict():
"""
AIによる予測を返すAPIのつもり
"""
return {'result': 'Prediction by AI.'}
if __name__ == '__main__':
app.run()
上記ファイルのあるディレクトリに移動し、
pyinstaller main.py --onefile
dist
ディレクトリに main.exe
ができているので、試しに実行してみます。
dist\main.exe
Traceback (most recent call last):
File "site-packages\PyInstaller\loader\rthooks\pyi_rth_pkgres.py", line 13, in <module>
File "c:\users\user\appdata\local\programs\python\python37\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 623, in exec_module
exec(bytecode, module.__dict__)
File "site-packages\pkg_resources\__init__.py", line 86, in <module>
ModuleNotFoundError: No module named 'pkg_resources.py2_warn'
[24508] Failed to execute script pyi_rth_pkgres
上のように、 ModuleNotFoundError
になる場合は、main.py
と同階層に生成された main.spec
ファイルをテキストエディタで編集します。
具体的には、 hiddenimports
に見つからなかったモジュール名を含めます。
# -- 略 --
hiddenimports=[],
# -- 略 --
↓次のように修正して保存。
# -- 略 --
hiddenimports=['pkg_resources.py2_warn'],
# -- 略 --
pyファイルではなく、修正したspecファイルを指定して、pyinstallerを実行します。
pyinstaller main.spec --onefile
再度動作確認します。
dist\main.exe
アクセスしてみると、Web APIが公開されていることをざっくり確認できます。
実際はC#などのアプリからこのEXEを実行し(要プロセス管理)、おなじくアプリからHttpクライアントでアクセスすることになります。