【Flet】 python main.py だと動くのに flet pack main.py だと動かない
SUCCESS!
結論:ビルド時に sudachipy
と sudachidict_core
を --add-data
オプションで追加すればよかった。
sudachipy は resources\sudachi.json
と resources\system.dic
を参照して動作する仕様なので、これらを同梱してビルドする必要がある(ちなみに後者はサイズが200MB超えのサイズなのでリポジトリには掲載不可)。
ところでこの同梱方法が所見では見抜けないトリッキーさ。
- 追加のデータがある場合は
ft.app()
でassets_dir
を指定するが、それに加えてビルドコマンドで--add-data
で明記してやる必要がある。 - しかもこのとき、セミコロン区切りで
(同梱したいファイル/フォルダ);(そのファイル/フォルダの中身の展開先)
のように指定する。後者が 展開先 なのが肝。 -
公式によると、 pyinstaller の
--add-data
は複数回指定できる。しかし、Flet がそのラッパーとして用意しているflet pack
コマンドは1つしか指定内容を引き受けてくれない模様。なのでビルド時は pyinstaller を直に使う。
2024-04-03 追記
--add-data
の代わりに --collect-data
を使えばOK!
最終的なビルドコマンドは下記:
pyinstaller --onefile --name yomi --collect-data sudachidict_core --collect-data sudachipy --noconsole main.py
site-packageディレクトリからコピーしてくる必要はなかった!
SudachiPy を使って読みを取得するアプリケーションを作りたい。
python main.py
で実行すると、下記のように問題なく実行できるのに、
flet pack main.py
で作られた exe ファイルを実行すると、 GO!
のボタンを押しても何も起きない…
試しに main
の関数内で直接、該当の関数を呼ぼうとすると、os error 3
の表示。
もちろん、python main.py
で実行すると問題なく動作する。
ブラウザで表示するようにして開発者ツールを開いても特に何のアラートもなし。
コンパイル時に sudachipy を正しくインポートできていない?
と、そこまで思い至ってもそこから先のデバッグ方法がわからず止まっています。ダレカタスケテ…
しかし同じ環境でインストールした Pillow を使っている下記のケースでは問題なく動作しているので謎。
sudachidict_code
などをさらに呼び出しているのが一因?
環境:
- Windows 11 Home
- Python 3.10.5
- Installed with Scoop
- Flet 0.3.2
SudachiPy 関連を別ファイルに分けて import する方式を辞めて、全部 main.py
のファイル単体にしてみたけれど効果なし
( ゚д゚)ハッ!
pack コマンドが内部で呼んでいる PyInstaller の問題なのでは…?
「PyInstaller OS Error 3」で検索してヒットした こちらの記事 を参考に、Dictionary()
インスタンス作成時の config_path
に sudachi.json
のパスを指定してやるとエラー文が変化した!
sudachi_dict
がないとのことなので main.py
内では使用していないもののまずは先頭で import してみる。
読み込んだライブラリが使用されていませんよ、という警告をひとまず無視して flet pack main.py
すると画面に変化が!
しかし今度はなにもコントロールが読み込まれない…
main.py
ではなく、自作のモジュールとして書いている sudachi.py
の中で関数を呼び出してみるとエラーの詳細が表示されることを発見。
でも sudachidict_core
はインストール済なのに何故…?
Dictionary()
インスタンス作成時に dict_type
を指定しても効果なし。上記の Issue で提案されている sudachipy link
コマンドは廃止されている模様。
Stack Over Flow に似たような質問を発見。
シンボリックリンク関連だから管理者権限で実行してみてはという提案がされていて sudachidict_core の再インストールや flet pack main.py
の再実行を管理者権限で実行しても効果なし
auto-py-to-exe を使って GUI から PyInstaller の各種オプションを弄り回してみる。
hidden_import
に sudachidict_core
を指定してコンパイル。ログを見るためにコンソールモードは有効化。
で、 exe を実行してみるとエラー文が変化。
system.dic
が存在しない…?
それではと試しに、 公式に書いてある方法 で Fly.io へのデプロイを試してみる。
すると以下のエラー文が出て失敗。
エラー文抜粋
#7 6.242 × Building wheel for sudachipy (pyproject.toml) did not run successfully.
#7 6.242 │ exit code: 1
#7 6.242 ╰─> [35 lines of output]
#7 6.242 running bdist_wheel
#7 6.242 running build
#7 6.242 running build_py
#7 6.242 creating build
#7 6.242 creating build/lib.linux-x86_64-cpython-311
#7 6.242 creating build/lib.linux-x86_64-cpython-311/sudachipy
#7 6.242 copying py_src/sudachipy/__init__.py -> build/lib.linux-x86_64-cpython-311/sudachipy
#7 6.242 copying py_src/sudachipy/command_line.py -> build/lib.linux-x86_64-cpython-311/sudachipy
#7 6.242 creating build/lib.linux-x86_64-cpython-311/sudachipy/dictionary
#7 6.242 copying py_src/sudachipy/dictionary/__init__.py -> build/lib.linux-x86_64-cpython-311/sudachipy/dictionary
#7 6.242 creating build/lib.linux-x86_64-cpython-311/sudachipy/tokenizer
#7 6.242 copying py_src/sudachipy/tokenizer/__init__.py -> build/lib.linux-x86_64-cpython-311/sudachipy/tokenizer
#7 6.242 creating build/lib.linux-x86_64-cpython-311/sudachipy/morphemelist
#7 6.242 copying py_src/sudachipy/morphemelist/__init__.py -> build/lib.linux-x86_64-cpython-311/sudachipy/morphemelist
#7 6.242 creating build/lib.linux-x86_64-cpython-311/sudachipy/morpheme
#7 6.242 copying py_src/sudachipy/morpheme/__init__.py -> build/lib.linux-x86_64-cpython-311/sudachipy/morpheme
#7 6.242 creating build/lib.linux-x86_64-cpython-311/sudachipy/resources
#7 6.242 copying py_src/sudachipy/resources/sudachi.json -> build/lib.linux-x86_64-cpython-311/sudachipy/resources
#7 6.242 copying py_src/sudachipy/resources/char.def -> build/lib.linux-x86_64-cpython-311/sudachipy/resources
#7 6.242 copying py_src/sudachipy/resources/rewrite.def -> build/lib.linux-x86_64-cpython-311/sudachipy/resources
#7 6.242 copying py_src/sudachipy/resources/unk.def -> build/lib.linux-x86_64-cpython-311/sudachipy/resources
#7 6.242 copying py_src/sudachipy/sudachipy.pyi -> build/lib.linux-x86_64-cpython-311/sudachipy
#7 6.242 running build_ext
#7 6.242 running build_rust
#7 6.242 error: can't find Rust compiler
#7 6.242
#7 6.242 If you are using an outdated pip version, it is possible a prebuilt wheel is available for this package but pip is not able to install from it. Installing from the wheel would avoid the need for a Rust compiler.
#7 6.242
manager and ensure it is on the PATH during installation. Alternatively, rustup (available at https://rustup.rs) is the recommended way to download and update the Rust compiler toolchain.
#7 6.242 [end of output]
#7 6.242
#7 6.242 note: This error originates from a subprocess, and is likely not a problem with pip.
#7 6.244 Building wheel for watchdog (setup.py): started
#7 6.244 ERROR: Failed building wheel for sudachipy
#7 6.677 Building wheel for watchdog (setup.py): finished with status 'done'#7 6.677 Created wheel for watchdog: filename=watchdog-2.2.1-py3-none-any.whl size=78958 sha256=50c11e86b95fc97eccbe7b93574854199ffc7c6cf65420bedf56cce88989ecca
#7 6.677 Stored in directory: /tmp/pip-ephem-wheel-cache-g7tmhfff/wheels/8d/98/0d/f9318ab1d63885b2dbd40c91dbfbde2a4e65fc6b40d135ad6b
#7 6.683 Successfully built watchdog
#7 6.683 Failed to build sudachipy
#7 6.683 ERROR: Could not build wheels for sudachipy, which is required to install pyproject.toml-based projects
------
Error failed to fetch an image or build from source: error building: executor failed running [/bin/sh -c pip install --no-cache-dir -r requirements.txt]: exit code: 1
そもそもの SudachiPy のビルドで失敗している模様。ローカルでは動いているのに。
そういえばローカルで初回設定したときに、SudachiPy が Rust で動くようになったので Rustup を入れた記憶がある。手元で動いているのはそのおかげに違いなく、であれば Docer 上でも同じことをすればいいはずなのにその方法が皆目わからずお手上げ。
少なくとも SudachiPy が一筋縄ではいかないことだけは確か。
エラー文を読み込むと、 system.dic
がないと書いてあるのはどうやら TEMP
フォルダの中身。ここに sudachi_dict パッケージをうまくコピーできていないのではないか、という仮説。