NuitkaはPythonのプログラムを実行可能ファイルにすることができるソフトです。
Nuitkaについてはこちらの記事が非常に参考になります。
この記事ではNuitkaで失敗しやすいポイントを解説します。
バージョン0.7時点の情報です。
特定のモジュールを含めるようにする
--follow-imports
オプションを使うと自動的に使用するモジュールをビルドしてくれますが、たまにうまく動作しない場合があります。
例えばeth-hash
モジュールでは、動的に必要モジュールを読み込むためか、動作に必要なeth_hash.backends.pycryptodome
をビルドしてくれません。
ビルドは通りますが、実行するとエラーになってしまいます。
このような場合は、--include-module
オプションを使用します。
--include-module=eth_hash.backends.pycryptodome
パッケージごと含めるようにするには、--include-package
を使用します。
--include-package=uvicorn
モジュールに必要なファイルを含めるようにする
モジュールによっては、pythonファイルの他に必要なファイルがあることがあります。
例えば、バージョンをversion.txtから読み込むようになっている場合、version.txtが無いとエラーになってしまいます。
その場合は、--include-data-file
を使用します。
例ではespnetモジュールですので、espnetフォルダ以下にversion.txtがコピーされるようにします。
--include-data-file="./venv/Lib/site-packages/espnet/version.txt=./espnet/"
パッケージ内のファイルを全て含めるようにするには、--include-package-data
を使用します。
--include-package-data=pyopenjtalk
プラグインを有効化する
いくつかのモジュールはプラグインを有効化する必要があります。
以下のコマンドでプラグインの一覧を確認できます。
$ python -m nuitka --plugin-list
The following plugins are available in Nuitka
--------------------------------------------------------------------------------
anti-bloat Patch stupid imports out of widely used library modules source codes.
data-files
dill-compat
enum-compat
eventlet Support for including 'eventlet' dependencies and its need for 'dns' package monkey patching
gevent Required by the gevent package
glfw Required for glfw in standalone mode
implicit-imports
multiprocessing Required by Python's multiprocessing module
numpy Required for numpy, scipy, pandas, matplotlib, etc.
pbr-compat
pkg-resources Resolve version numbers at compile time.
pmw-freezer Required by the Pmw package
pylint-warnings Support PyLint / PyDev linting source markers
pyqt5 Required by the PyQt5 package.
pyside2 Required by the PySide2 package.
pyside6 Required by the PySide6 package for standalone mode.
pyzmq Required for pyzmq in standalone mode
tensorflow Required by the tensorflow package
tk-inter Required by Python's Tk modules
torch Required by the torch / torchvision packages
--plugin-enable
オプションをつけることでプラグインを有効化できます。
--plugin-enable=numpy
どうしてもビルドできないモジュールを除外する
どうしてもビルドできないモジュールというものが出てきます。
しかし、実際の動作に不必要なモジュールだった場合、無理やり依存を外してビルドすることができます。
--nofollow-import-to
オプションで特定のモジュールの自動インポート(ビルド)をやめることができます。
--nofollow-import-to=sklearn
このままでは、importしている所などでエラーが出てしまいますので、プラグインを自作して解決します。
以下の例では、librosaというモジュールが依存するsklearnというモジュールがビルドできず、かつ不要だったためインポートしないようにしています。
(fix_build.py)
from nuitka.plugins.PluginBase import NuitkaPluginBase
class NuitkaPluginFixBuild(NuitkaPluginBase):
plugin_name = "fix-build"
@staticmethod
def onModuleSourceCode(module_name, source_code):
if module_name == "librosa.decompose":
source_code = source_code.replace("import sklearn.decomposition", "#")
elif module_name == "librosa.segment":
source_code = source_code.replace("import sklearn", "#")
return source_code
作ったプラグインを--user_plugin
オプションで有効にします。
--user-plugin=fix_build.py
Github Actionsでビルドを行う
ビルド中にyes/noを聞かれる場合があり、Github Actionsの場合そこでビルドが止まってしまいます。
--assume-yes-for-downloads
オプションをつけることで対処できます。
その他
公式マニュアル
プラグインのマニュアル
余談
この記事は、紹介した記事でも言及されているVOICEVOXというソフトの派生ソフトを作ったときの備忘録です。
一回のビルドに2、3時間かかるので大変でした。
ちなみにvoicevox_engineの.github/workflows/build.yml
に自動ビルドの処理が書いてあるので参考になるかもしれません。
(nuitkaとは無関係な処理が多いですが...)