はじめに
Pythonを配布しやすいように、実行可能形式で配布できたらいいのに…ということで、今回は、pythonスクリプトを単一の実行可能形式にする方法を解説します。
あくまで、覚書ですので、参考までにどうぞ。
インストール
Python で ファイルを 単一実行ファイル化するには pyinstaller を使用します。まずは pyinstaller をインストールしましょう。
基本的には以下のコマンドでインストールできます
pip install pyinstaller
環境によっては
pip3 install pyinstaller
や、組み込み用のpythonの場合は
python -m pip install pyinstaller
のように実行します、注意点としてはpipで以下のようなエラーが出た場合
Traceback (most recent call last):
File "/usr/bin/pip", line 9, in <module>
from pip import main
ImportError: cannot import name main
は、
python -m pip install pyinstaller
と、pipモジュールを指定して呼ぶか、/usr/bin/pipをvimなどで開いて
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())
と書き換えてしまいましょう、場合によっては
from pip import main
if __name__ == '__main__':
sys.exit(main())
の部分を
from pip import __main__
if __name__ == '__main__':
sys.exit(__main__._main())
と書き換えることでも対応できます
実際に作成してみよう
基本的に、以下の形式で実行します
pyinstaller pythonファイル名 [--onefile] [--noconsole] [--windowed]
- よく使うオプション
挙動 | オプション | 概要 |
---|---|---|
コンパイルする | --onefile | 関連するファイルを1つにまとめてバイナリ化します |
非コンソール表示 | --noconsole | コンソールアプリでもコンソール表示をしないようにします |
Windowsバイナリ生成 | --windowed | 異なるプラットフォームでもWindowsのバイナリを作ります |
データバインド | --add-data | バイナリ内部にファイルを取り込みます |
管理者モード実行 | --uac-admin --uac-uiaccess | 管理者モードで実行するバイナリを作ります |
よくあるサンプル
#!/usr/bin/python
# -*- coding: utf-8 -*-
print("hello world")
#Mac Linuxの場合
pyinstaller hello.py --onefile
#Windowsの場合
pyinstaller hello.py --onefile --windowed
実際に実行したログ
pyinstaller hello.py --onefile
302 INFO: PyInstaller: 3.4
302 INFO: Python: 3.4.8
302 INFO: Platform: Linux-3.10.0-693.11.1.el7.x86_64-x86_64-with-centos-7.4.1708-Core
303 INFO: wrote /home/pyuser/hello.spec
326 INFO: UPX is not available.
327 INFO: Extending PYTHONPATH with paths
['/home/pyuser', '/home/pyuser']
327 INFO: checking Analysis
327 INFO: Building Analysis because Analysis-00.toc is non existent
328 INFO: Initializing module dependency graph...
346 INFO: Initializing module graph hooks...
347 INFO: Analyzing base_library.zip ...
25932 INFO: Processing pre-find module path hook distutils
49391 INFO: running Analysis Analysis-00.toc
49967 INFO: Caching module hooks...
50029 INFO: Analyzing /home/pyuser/hello.py
50189 INFO: Loading module hooks...
50190 INFO: Loading module hook "hook-pydoc.py"...
50190 INFO: Loading module hook "hook-encodings.py"...
51815 INFO: Loading module hook "hook-distutils.py"...
51817 INFO: Loading module hook "hook-xml.py"...
58878 INFO: Looking for ctypes DLLs
58960 INFO: Analyzing run-time hooks ...
59001 INFO: Looking for dynamic libraries
63887 INFO: Looking for eggs
63887 INFO: Using Python library /lib64/libpython3.4m.so.1.0
63929 INFO: Warnings written to /home/pyuser/build/hello/warn-hello.txt
64350 INFO: Graph cross-reference written to /home/pyuser/build/hello/xref-hello.html
64534 INFO: checking PYZ
64534 INFO: Building PYZ because PYZ-00.toc is non existent
64534 INFO: Building PYZ (ZlibArchive) /home/pyuser/build/hello/PYZ-00.pyz
68757 INFO: Building PYZ (ZlibArchive) /home/pyuser/build/hello/PYZ-00.pyz completed successfully.
68879 INFO: checking PKG
68879 INFO: Building PKG because PKG-00.toc is non existent
68880 INFO: Building PKG (CArchive) PKG-00.pkg
90765 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
90806 INFO: Bootloader /usr/lib/python3.4/site-packages/PyInstaller/bootloader/Linux-64bit/run
90806 INFO: checking EXE
90806 INFO: Building EXE because EXE-00.toc is non existent
90807 INFO: Building EXE from EXE-00.toc
90807 INFO: Appending archive to ELF section in EXE /home/pyuser/dist/hello
91052 INFO: Building EXE from EXE-00.toc completed successfully.
実行すると、buildとdistというフォルダが作成されます。
大体の場合、以下のような構造になると思います。
./hello.py
./hello.spec
./build/hello/base_library.zip
./build/hello/warn-hello.txt
./build/hello/xref-hello.html
./build/hello/Analysis-00.toc
./build/hello/PYZ-00.pyz
./build/hello/PYZ-00.toc
./build/hello/PKG-00.pkg
./build/hello/PKG-00.toc
./build/hello/EXE-00.toc
./dist/hello
./__pycache__
./__pycache__/hello.cpython-34.pyc
dist以下にできているものが、生成された単一ファイルで、そのほかのファイルは生成時の中間ファイルになります。
上記はCentOS7.4上で実行しています、とりあえず実行してみましょうか
./dist/hello
hello world
単一コマンドにしてしまえば、配布も楽ですね
さいごに
pythonの単一ファイル化は他にも方法がありますので、ここで説明しているのは一例にすぎません
あくまで参考にしてください。