Pythonを独立したExeファイルとして書き出すPyInstallerの記事を以前書きました。
しかし、この方法よりも実行がより高速、より軽量な方法がありました。
embeddable pythonと呼ばれるもので、Windows限定ではありますが、ダウンロードしてきた圧縮状態なら 7 MB、解凍しても 14 MB程度のPython実行環境です。
もちろんこのままではパッケージを使えませんので、そのパッケージ導入方法も合わせて記載します。
ダウンロード
上記ページにあるWindows x86-64 embeddable zip fileをダウンロードして解凍。
もしくは、WindowsPowerShellで以下を実行。(wgetが使えるため楽だから)
# 作業用フォルダへ移動(適当なところでOK)
cd (適当なところ)
# PowerShellのwgetでファイルをダウンロード(ウィルス対策ソフトに注意)
wget "https://www.python.org/ftp/python/3.6.4/python-3.6.4-embed-amd64.zip" -O "epython_zip.zip"
# 解凍
Expand-Archive -Path epython_zip.zip -DestinationPath epython
最小構成
pythonNN.dll、pythonNN.zip、vcruntime140.dllがあればPythonは動作します。
python.exeは、pythonNN.dllへ引数を送るだけの実行ファイルですので、独自C++に組み込むときは必要ありません。
(pythonNN.zipは圧縮ファイルですが、このままで機能しますので解凍してはいけません。)
今回は他の構成ファイルを使うのでそのままにしておいてください。
PIP
pythonNN._pth
ファイルを修正。
そのままではget-pip.py
が使えないので、少し手直しをする必要があります。
ダウンロードしてきたファイルの中にあるpython36._pth
というファイルをエディタで開いて、
# import site
を、
import site
とコメント解除する必要があります。
python 3.6 embed cannot get pip · Issue #7 · pypa/get-pip · GitHub
それから、https://bootstrap.pypa.io/get-pip.py
のファイルをダウンロードするか、ダウンロード処理をPowerShellで以下の通りに実行。
# 解凍したepythonの中身へ移動
cd epython
# そのままではwgetでダウンロードできないので、下記を実行(PowerShellではデフォルトでTLS1.2が非対応のため)
# 一時的にTLS1.2を有効にします(PowerShellを閉じると解除される)
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
# Wget
wget "https://bootstrap.pypa.io/get-pip.py" -O "get-pip.py"
コマンドプロンプトで作業
これでget-pip.py
が使えるのでインストール作業をしますが、
ここからはコマンドプロンプトで作業します。(PowerShellではモジュールエラーで実行出来なかった。)
要注意点
get-pip
に限らず、ルート環境にpythonがインストールされているときはembeddable pythonなのかルート環境なのかを注意して実行すること。(作業フォルダにembeddable pythonがあるかどうか。もしくはpip
インストール後にpython -m pip list
等でパッケージの中身を見て確認。)
cd (embeddable pythonのフォルダ)
# 念の為、python.exeがあるディレクトリか確認。
dir
# リストの中にpython.exeがあれば、get-pipをインストール
python get-pip.py
これでpip
が使えるようになりました。
ただし、
# NG
# pip install numpy
# OK
python -m pip install numpy
のようにpython -m pip install (パッケージ名)
の書式でなければなりません。
試しにMatplotlibとWxPython
試しにMatplotlibを使ってグラフを書きつつ、wxPythonで描画してみましょう。
Package
以下のようにパッケージをインストール
python -m pip install numpy
python -m pip install matplotlib
python -m pip install wxpython
テストスクリプト
テストスクリプトは下記URLから引用。
main.py
という名前でpython.exe
と同じ階層に保存してください。
スクリプト引用元
python - Embedding a matplotlib figure inside a WxPython panel - Stack Overflow
#! env python
# -*- coding: utf-8 -*-
from numpy import arange, sin, pi
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import wx
class CanvasPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
self.canvas = FigureCanvas(self, -1, self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
self.Fit()
def draw(self):
t = arange(0.0, 3.0, 0.01)
s = sin(2 * pi * t)
self.axes.plot(t, s)
if __name__ == "__main__":
app = wx.PySimpleApp()
fr = wx.Frame(None, title='test')
panel = CanvasPanel(fr)
panel.draw()
fr.Show()
app.MainLoop()
バッチファイルを保存
同じ階層にバッチファイルをmain.cmd
という名前で以下のように記載して保存。
# このファイルの位置を作業ディレクトリに
cd /d %~dp0
# main.pyを実行
python.exe main.py
main.cmd
を実行するとグラフが描画される。
容量
ディレクトリの容量は 183 M程度になりました。
パッケージを含めると流石に容量が大きいですが、しかし、速度はPyInstallerより高速に動いている感じがします。
C++にembeddable pythonを埋め込む
別の記事として編集中。そのうち気が向いたときにでも書いていきます。
公式
1. 他のアプリケーションへの Python の埋め込み — Python 3.6.4 ドキュメント
Python/C API リファレンスマニュアル — Python 3.6.4 ドキュメント