概要
Windowsユーザーへ自作のPythonアプリを配布する際,pyinstallerによるバイナリ化が一般的であると考える.しかし,これが何らかの理由により,多くの場合で失敗するため,これの代わりとなる方法として,embeddableバージョンのPythonを利用する方法を記す.
考慮している点
配布されるユーザーは,~~パソコンに関して疎く,~~プログラミングに対する知識が全くないと仮定し,彼らがなるべく簡単な操作でこれをできるようにする.
環境
Windows 10 1903 64bit
で確認済み
実際にこの配布方法を利用した自作プロジェクト
video_to_picture_everyseconds:開始時間と間隔の時間を設定すると,それに合わせて動画から静止画をキャプチャするプログラム~~(私の作ったプログラムの宣伝です)~~
方法
ディレクトリ構造は以下のように作成する.今回の例であるプロジェクトmy_project
では,プロジェクト名もアプリ名もmy_project
とする.
my_project/
├── install.bat
├── my_project.bat
├── powershell
│ ├── install.ps1
│ └── my_project.ps1
├── requirements.txt
└── src
└── my_project.py
プログラム側とユーザー側がそれぞれやること
プログラム側がやること
Pythonのインストール
-
python.orgから
Windows x86-64 embeddable zip file
をダウンロードし,これを展開する.(なお,厳密には,圧縮ファイルのダウンロードと展開をするだけですが,Pythonをインストールする
との表現を用います.) - 展開したPythonに
pip
をインストールする. -
pip install -r requirements.txt
する.
該当の自作アプリmy_project
の起動
- インストールしたPythonから,該当の自作アプリ
my_project
のPythonスクリプトmy_project.py
を起動する.
ユーザー側がやること
- Pythonのインストール:プロジェクトフォルダ
my_project/
の中にあるinstall.bat
をクリックする. - 該当の自作アプリ
my_project
の起動:プロジェクトフォルダmy_project/
の中にあるmy_project.bat
をクリックする. - Pythonと該当の自作アプリ
my_project
のアンインストール:my_project/
を削除するだけでよい.
アプリmy_project
内での操作を除けば,ユーザーは,クリック以外の操作は行わなくてよい.よって,ユーザーには,install.bat
とmy_project.bat
のみを操作し,他のファイルやフォルダは決して触らないように指示すればよい.
それぞれのフォルダとスクリプトの詳細について
それぞれのフォルダについて
my_project/src/
このフォルダには,自作アプリmy_project
のPythonのスクリプトが入っている.この例では,メインとなるスクリプトをmy_project.py
とする.
my_project/powershell/
このフォルダには,Python本体のインストールやPythonのスクリプトmy_project/src/my_project.py
の実行に必要な,PowerShellのスクリプトmy_project/powershell/*.ps1
が入っている.これらのPowerShellのスクリプトはバッチファイルmy_project/*.bat
を介して実行する.また,このことからPowerShellのスクリプト内のパスは,my_project/
がカレントディレクトリとして考えられている.
なお,バッチファイルを介さず,PowerShellファイルを直接実行しても問題はないが,これのダブルクリックによる実行は,デフォルトでは不可能であるため,(特にパソコンに疎い)ユーザーにとって困難となりうる1.また,バッチファイルから直接Pythonを実行する場合,セキュリティの設定など,複雑な操作が困難であるため,バッチファイルからPowerShellを介した処理を行っている.
それぞれのスクリプトについて
インストールのためのスクリプト
この例では,Pythonのバージョンが3.6.8,amd64となっているが,必要に応じて,変更してもかまわない.変更する部分は,3.6.8
,amd64
,python36._pth
と書いてある部分である.
まずは,PowerShellのスクリプトであるmy_project/powershell/install.ps1
を示す.
# Download Python
if(!(Test-Path "python-3.6.8-embed-amd64.zip")){
wget "https://www.python.org/ftp/python/3.6.8/python-3.6.8-embed-amd64.zip" `
-O "python-3.6.8-embed-amd64.zip"
}
## my_project/にPythonをダウンロードする.
## サーバーpython.orgに,不要な負荷をかけないため,すでにダウンロードされている場合は,ダウンロードしない.
Expand-Archive -Path python-3.6.8-embed-amd64.zip -DestinationPath python-3.6.8-embed-amd64 -Force
## ダウンロードしたファイルを展開する.
## すでにある場合は,上書きする.
# Download get-pip
cd python-3.6.8-embed-amd64
## 展開したフォルダに入る.
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
## wgetを使うため,セキュリティの設定を変更する.
## このスクリプトが終了したら,変更されたセキュリティの設定はスクリプトの実行前の状態に戻る.
wget "https://bootstrap.pypa.io/get-pip.py" -O "get-pip.py"
## get-pip.pyをダウンロードする.
Add-Content -Path ./python36._pth -Value "import site" -Encoding UTF8
## get-pip.pyを実行するため,python36._pthにimport siteを追記する.
## 編集前のpython36._pthでは,これがコメントアウトされている.
./python get-pip.py
## get-pip.pyを実行する
# Install additional packages for my_project.py
cd ../
./python-3.6.8-embed-amd64/python -m pip install -r requirements.txt
## pip install -r requirements.txtを行う.
次に,バッチファイルのスクリプトであるmy_project/install.bat
をしめす.バッチファイルに日本語を表記すると,文字化け等の問題が生じる恐れがあるため,コメントアウトは英語で表記する.
@echo off
@rem This makes the batch file not appear anything which is not needed for users.
echo Installing...
powershell -NoProfile -ExecutionPolicy Unrestricted .\powershell\install.ps1
@rem Chenge security setting to launch my_project/powershell/install.ps1.
@rem This setting return when this batch file is done.
echo Completed
pause
自作アプリを実行するためのアプリ
まずは,PowerShellのスクリプトであるmy_project/powershell/my_project.ps1
を示す.
# Launch src/my_project.py
./python-3.6.8-embed-amd64/python ./src/my_project.py
次に,バッチファイルのスクリプトであるmy_project/my_project.bat
をしめす.
@echo off
powershell -NoProfile -ExecutionPolicy Unrestricted .\powershell\my_project.ps1
pause
自作アプリにてtkinterを使用した場合
上記の方法での一番の欠点は,tkinterを利用できないことである.ただし,Open-file dialogのためだけにtkinterを用いる場合,my_project/powershell/my_project.ps1
を改良することで,対処が可能である.
[void][System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
$dialog = New-Object System.Windows.Forms.OpenFileDialog
# おまじない
$dialog.Filter = "VIDEO FILE(*.MOV;*.MP4;*.AVI)|*.MOV;*.MP4;*.AVI"
# Open-file dialogにて,選択するファイルの種類を指定する.
$dialog.InitialDirectory = "~/Desktop"
# Open-file dialogがデフォルトで表示するフォルダを指定する.
$dialog.Title = "Choose the video file"
# Open-file dialogで表示するタイトルを指定する.
if($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK){
./python-3.6.8-embed-amd64/python ./src/my_project.py $dialog.FileName
# Open-file dialogでファイル名を正常に取得した場合,my_project/src/my_project.pyを実行する.
}
なお,my_project/src/my_project.py
では,以下に示すように,sys.argv[1]
などで,コマンドライン引数を取得できるようにする.
import sys
filename = sys.argv[1]
参考文献
超軽量、超高速な配布用Python「embeddable python」(このページに書かれているものは,左のページに載っているものを自動化したものです.)