pyside2アプリケーションをQt 5.12.1に基づいてすべての主要な3つのオペレーティングシステム( Windows、Linux、MacOS)。
私はすでにチェックしました Pythonスクリプトスタンドアロン実行可能ファイルを依存関係なしで実行する方法は? ですが、次のようなQt関連のアプローチが必要なので、それは私が望むものではありませんwindeployqt
、macdeployqt
、linuxdeployqt
(個別のプロジェクト)。
Eyllanescが指摘したように: "pythonはバイナリを生成しないスクリプト言語です"。しかし、The Qt Companyもそれを理解し、pyside2アプリケーションを展開しやすくする必要があります。少なくともC++/QMLアプリケーションのデプロイと同じくらい簡単です。
windowsdeployqt、macdeployqt、linuxdeployqt...のようなツールが欲しいpyside2アプリケーションで動作します。
[UPDATE]eyllanesc推奨 fbs(fmanビルドシステム) デプロイする公式のツールがないため、開始点としてpyside2アプリケーション。これは回避策として機能するはずです。新しい答えも大歓迎です。
Qt Companyが公式ツールをリリースしたら、できるだけ早く回答してください。
[注意]:Qt Creator 4.8.1を使用していますQt 5.12.1
シンプルなアイデアですが、問題は最小限のセットを見つけることです。 qtサイトで提案されたパッケージャは、複雑なファイル構造と独自のEXEを作成しますが、これは小さなスクリプトの場合(IMHO)には多すぎます。幸い、依存関係をログに記録する方法があります。Windowsでは Process Monitor 、Linuxでは strace です。監視対象プログラムのすべてのシステムコールがリストされます。そのようなログから依存関係を選択するための小さなpythonスクリプトを記述しました。
ここに示すように、仮想環境でこれを実行すると便利です。または、python組み込みディストリビューションの必須モジュールがあらかじめインストールされています:
> python -m venv ./MyVEnv
> cd ./MyVEnv
> ./.../python -m pip install pyside2
-B
フラグを使用して、キャッシュされたファイルが最終パックに含まれないようにすることが役立つ場合があります。また、監視プログラムで不要なシステムコールを手動で除外して、ログを減らすこともできますwindowsの場合:
> Procmon /AcceptEula /NoFilter /BackingFile log1
> .\MyVEnv\...\python -B yourScript.py
> Procmon.exe /OpenLog log1.PML /SaveAs logFile.csv
linuxの場合:
> 2>logFile strace ./bin/python3 -B yourScript.py
その後、スクリプトを起動して、ログに記録されたすべての依存関係をフォルダーに複製し、元のファイル構造を保持します。
> python .\depspicker.py
それは:
#depspicker.py
#changes from Windows to Linux version commented
logF = r".\logFile.CSV" #Linux: ./logFile
basePath = r".\...\site-packages" #base of the file-tree to be copied (where the needed dependencies originally reside)
destPath = r".\site-packages" #destination of copy
import csv, shutil
from pathlib import Path
logF = Path(logFile)
basePath = Path(basePath).resolve()
destPath = Path(destPath).resolve()
with open(logF, newline='', encoding="utf-8") as log:
checked = set()
reader = csv.DictReader(log) # Linux: -
for row in reader: #Linux: for row in log:
try:
src = Path(row["Path"]) # Linux: src = Path(row.split('"')[1])
src = src.resolve()
if src in checked or not (src.is_file() and\
basePath.parts == src.parts[:len(basePath.parts)]):
continue
except (OSError, IndexError): #not a file
continue
finally:
checked.add(src)
dst = destPath / src.relative_to(basePath)
dst.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dst.parent)