QMLやアイコンなどのファイルもリソースとしてpythonアプリの実行ファイル形式(exe化)に含める方法

前回はQMLファイルを使ったpythonによるGUIアプリの作成手順を解説しました。

Qt for Python(PySide2)をQMLで開発するための環境構築Qt for Python(PySide2)をQMLで開発するための環境構築

今回は作成したアプリを配布する際の事を考えてみます。

配布の際には、作成したpythonコードをWindowsであればexe、Macであればapp形式などに変換するとpythonをインストールしていない人でも動かすことができるので便利です。

これらの実行形式に変換するには、pyinstollerやcx_Freeze、py2exeなどが使えますが、実際のやり方はほかの記事に譲るとして、やってみるとひとつ重大な問題があることが分かります。

QMLを使ったプロジェクトを実行形式にして起動してみると、表示されない。。。

どうやらQMLファイルの読み込みに失敗しているようです。

つまり、実行形式の中にQMLファイルを含められていないということですね。これは、アイコンなどの画像ファイルについても同じことが言えます。

この記事では、それらのファイルも実行形式に含めて配布できるようにするにはどうしたらいいかを解説します。

リソースファイルをpyファイルにして埋め込めばいい

この問題に対するソリューションとしては、

リソースファイルを.pyに変換してしまえば、自然に実行形式にも含まれるし、そのファイルを使うのも、import文でインポートすればいい

というものです。

PySide2にはpyside2-rccという、リソースファイルを.pyファイルに変換するツールが付属していますので、それを使うことにしましょう。

はじめに、「pyqt5_qml.qrc」など、.qrcという拡張子の定義ファイルを作成し、この中にリソースを記述していきます。

リソース記述例(pyqt5_qml.qrc):

<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix = "qml">
    <file>QtProject1.qml</file>
    <file>QtProject2.qml</file>
</qresource>
</RCC>

fileのタグにqmlやアイコン用ファイルを追加していきます。

prefix属性を使うと、フォルダ分けのように、種類の異なるファイルをまとまりで管理できます。

リソースの定義ができたら、それをpyside2-rccで.pyファイルに変換します。

-0オプションで変換後のファイル名を指定しますが、慣例として、pyqt5_qml.qrc⇒pyqt5_qml_qrc.pyのように.qrcを_qrcにして.pyを付けるとわかりやすいです。

//pyside2-rccはsite-packageの下に入っている
//以下はpyqt5_qml.qrc⇒pyqt5_qml_qrc.pyの例

site-packages\PySide2\pyside2-rcc.exe -o pyqt5_qml_qrc.py pyqt5_qml.qrc

.pyファイルに変換したら、importすればpyファイルの中で使用できます。

前回の記事のQMLを使ったアプリのソースの中で使うとしたら、以下のようになります。

import sys
 
import pyqt5_qml_qrc
 
from PySide2 import QtCore
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
 
 
if __name__ == '__main__':
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
 
    for x in QtCore.QDir(':qml').entryList():
        print(x)
 
    engine.load(QtCore.QUrl('qrc:/qml/QtProject1.qml'))
 
    if not engine.rootObjects():
        sys.exit(-1)
 
    sys.exit(app.exec_())

少し解説すると、

import pyqt5_qml_qrc  で、.py化したリソースを読み込んで、

qrc:/qml/QtProject1.qml で使っていますよね。「qml」がprefixに対応していることが分かります。

少し上のprint(x)分では、読み込んだリソースを出力しています。確認用のデバッグなので、必要ない人は消しても大丈夫です。

以上で、リソースファイルを配布時にも実行形式に含めることができるようになりました。

次回はいよいよ、作成したアプリを実行形式にして配布し、みんなに使ってもらうことに挑戦しましょう!