追記:18-10-31 パッケージのインストールエラーに対応する方法を追記
追記:20-11-18 エラー対応に追記
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
(pythonのバージョンによって数字部分が変わる)というファイルをエディタで開いて、
# import site
を、
import site
とコメント解除する必要があります。
python 3.6 embed cannot get pip · Issue #7 · pypa/get-pip · GitHub
※ pythonのバージョンによっては、以下の1行もpython36._pth
に追記します。(コメントの@alphya様からの情報)
./Lib/site-packages
それから、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"
pthファイル
上記記事にあるように、3.6系以上のバージョンの場合は、ダウンロードしてきたpython.exe
と同じディレクトリに適当なファイル名に.pth
拡張子をつけたファイルを作成し、以下の内容を記載して保存します。
import sys; sys.path.append('')
コマンドプロンプトで作業
これでget-pip.py
が使えるのでインストール作業をしますが、
ここからはコマンドプロンプトで作業します。(PowerShellではモジュールエラーで実行出来なかった。)
要注意点
get-pip
に限らず、ルート環境にpythonがインストールされているときはembeddable pythonなのかルート環境なのかを注意して実行すること。(作業フォルダにembeddable pythonがあるかどうか。もしくはpip
インストール後にpython -m pip list
等でパッケージの中身を見て確認。)
pip、get-pip関係のエラーは下部のエラー対策箇所にまとめておきました
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 --no-cache-dir install -I -U 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
という名前で以下のように記載して保存。
rem このファイルの位置を作業ディレクトリに
cd /d %~dp0
rem main.pyを実行
python.exe main.py
main.cmd
を実行するとグラフが描画される。
容量
ディレクトリの容量は 183 M程度になりました。
パッケージを含めると流石に容量が大きいですが、しかし、速度はPyInstallerより高速に動いている感じがします。
エラー対応
“python setup.py egg_info” failed with error code 1
python -m pip install パッケージ名
上記のようにパッケージを追加しようとしたときエラーが表示されることがあります。
このエラーの原因は、zipファイル内のlib2to3というパッケージの中身が展開出来ないことによるもののようです。
対応方法としては、
1.同封の「PythonNN.zip」を失敗した時の為にバックアップ、コピーしておく。
2.「PythonNN.zip」をフォルダとして展開。
3.「PythonNN」というフォルダ名から「PythonNN.zip」に変更。
“python setup.py egg_info” failed with error code 1
https://stackoverflow.com/questions/42962765/embedded-python-3-5-python-setup-py-egg-info-failed-with-error-code-1
解決しない場合
setuptoolsのバージョンをダウングレードして解決する場合があります。これは、2to3をサポートしなくなったことに由来するとのこと。
python -m pip install setuptools==57.4.0
ERROR: Could not install packages due to an OSError: .....
Python.h pythonNN.lib
Python.hが見つかりません
や、 'python37.lib' を開くことができません。
といった旨のエラーが出た場合は、python -m pip install ....
コマンドを実行する前にそのファイルが含まれるパスを以下のコマンドで追加します。
また、この手のエラーはコンパイラも必要となる場合もあります。 Visual Studioやbuild toolsをインストールしたりしましょう。
例えば、AnacondaやMinicondaのがインストールされている場合は、以下のようになります。(例はMiniconda)
SET INCLUDE=C:\ProgramData\Miniconda3\include;%INCLUDE%
SET LIB=C:\ProgramData\Miniconda3\libs;%LIB%
ModuleNotFoundError: No module named XXX
同じ階層にpyファイルがあり、それをimportしようとしてエラーが発生した場合、その発生箇所よりも前に、以下のスクリプトを追加する。
sys.path.append(os.path.dirname(os.path.abspath(sys.argv[0])))
公式
1. 他のアプリケーションへの Python の埋め込み — Python 3.6.4 ドキュメント
Python/C API リファレンスマニュアル — Python 3.6.4 ドキュメント