8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

EAGLYSAdvent Calendar 2021

Day 19

Pyinstaller を自作ライブラリ/サービスに対して使用するときのチュートリアル② (pip モジュールの参照)

Posted at

@kenmaroです。
普段は主に秘密計算、準同型暗号などの記事について投稿しています
秘密計算に関連するまとめの記事に関しては以下をご覧ください。

はじめに

このチュートリアルは2本立てです。

前回の記事はこちらから

概要

python で書かれたスクリプト、ライブラリなどをバイナリ化し、ソースコードが見えないようにした状態で配布することはよくあると思います。
そんなときにpyinstallerを使うと便利であり、いろいろな解説記事なども転がっているため比較的取り組みやすいと思います。

しかしながら、解説記事などではあくまでも簡単なhello_world的なプログラムをバイナリ化するような記事が多く、

  • 実際に割と大きめのライブラリ(階層構造などを持ったもの)をバイナリに書き出したい。
  • pip install したライブラリを使用しているプログラムをバイナリに書き出したい。

と言うような実運用上必ず通るようなケースでどのようにpyinstallerを用いればよいか、
まとまっているものがあまり無いように感じたため、今回は運用の仕方についてまとめてみます。

この記事でわかること

pyinstaller を用いてpython プログラムをバイナリ化して配布する際、

  • プログラムがpip install したライブラリを使用しているときにそれらも含めてバイナリ化するにはどうしたらいいか

がわかります。

階層構造

前回の記事で使ったmyprojectというライブラリをpyinstallerでバイナリ配布するシナリオを引き続き考えていきます。
階層構造は以下のようでした。

main.py
myproject/
  core.py
  server/
    controller/
      controller.py
    service/
      service.py

pip モジュールを使っているとき

ここで、例えば、service.py の中において、

service.py
import numpy as np

と言うような記述があったとします。
pipモジュールを何も使わずにサービスを作ることは考えにくいので、このような記述はいろいろなところにあると想定されます。

このとき、pyinstallerの実行のときに、このバイナリがnumpyに依存している、ということを明示することで、
pyinstaller はその依存関係をきちんとリンクした状態でバイナリを生成してくれます。

以下ではその依存関係の記述の仕方をまとめます。

hook にpip の依存関係を記述する

以前の記事でもhookについて言及しましたが、pipモジュールについても、hookにどのモジュールを使っているか記述することになります。
以前のhookは以下のようでした。

pyinstaller/hooks/hook-myproject.py
hiddenimports = [
"myproject.core",
"myproject.server.controller.controller",
"myproject.server.service.service",
]

これに対して、numpyが依存関係として存在しているのであれば、

pyinstaller/hooks/hook-myproject.py
hiddenimports = [
"numpy",
"myproject.core",
"myproject.server.controller.controller",
"myproject.server.service.service",
]

とするだけです。

hookに書くモジュールの名前を取得する

このとき、numpyのようにそのまま書きましたが、
実際はpython がpip install したあとの site-packages の中で、ライブラリがどの名前で参照されているかを
きちんと確認する必要があります。

この参照の仕方ですが、以前記事にしていたのでぜひご覧ください。

結論だけ言うと、使っているpython環境のsite-packagesの場所は、

python -c "import site; print (site.getsitepackages())"

でパスを参照することができます。
このパスにcdしたあと、ls -l
を行い、どのモジュールをpyinstallerが参照するべきか書く必要があります。

もしpyinstaller がこのモジュールの名前を参照できない場合、

pyinstaller を走らせたときに、

WARNING: Hidden import "numpy" not found!

と言うようなワーニングが吐き出されますので、きちんとログを確認する必要があります。
ワーニングですので、そのままバイナリ自体は吐き出され、
バイナリを実行しようとすると、ランタイムにおいて、

no module found numpy

のようなエラーとなるのでご注意ください。

まとめ

今回は、前回の記事に引き続き、
Pyinstallerを実際に運用するときにあったら便利だと思われる項目を

  • pip でインストールしたモジュールの参照の仕方

というテーマで書いてみました。

前回の

  • 階層構造を持ったモジュールに対して、実行ファイル(main.py)のバイナリ化

のやり方と合わせると、かなり汎用的にPyinstallerを使いバイナリ化が行えるようになります。

もし、Python のプログラムをそのまま配布するわけにはいかず、バイナリ化などの工夫が必要だ、
でもPyinstaller どうやって使えばいいんだろう、

となった際は是非参考にしてみてください。

今回はこの辺で。

@kenmaro

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?