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とは無関係な処理が多いですが...)