Using fbs to package a PyQt5 app, what could be the cleanest way to access resource files from non-GUI code?
In the example below, I made a simple PyQt5 app with one window containing one button. The button triggers a function that will read a .json
resource file and print its attribute message
in the console. The function print_data()
defined in logic.py should also work without the GUI app, for example to be used by other python scripts. Therefore, it cannot be move as a method of the MainWindow class.
It is easy and handy to use the application context's get_resource()
method to get the path to mainwindow.ui. Unfortunately, it cannot be used by print_data()
to get the path to static_data.json as the function has no access to the application context.
What would be the best solution?
- Use fbs's resources system only for gui-related resource files and keep static_data.json with the python files?
- Try to access the application context outside of the MainWindow class?
- Use another python resources library such as pkg_resources to handle non gui-related resource files?
- Use another tool such as cx_freeze to package the app?
Directory structure:
|-- src
| |-- main
| | |-- python
| | | |-- main.py
| | | |-- gui.py
| | | |-- logic.py
| | |-- resources
| | | |-- base
| | | | |-- mainwindow.ui
| | | | |-- static_data.json
Content of main.py
:
from fbs_runtime.application_context.PyQt5 import ApplicationContext
import sys
from gui import MainWindow
if __name__ == '__main__':
appctxt = ApplicationContext()
window = MainWindow(appctxt)
window.show()
exit_code = appctxt.app.exec_()
sys.exit(exit_code)
Content of gui.py
:
from PyQt5.QtWidgets import QMainWindow
from PyQt5 import uic
from logic import print_data
class MainWindow(QMainWindow):
def __init__(self, context):
super().__init__()
# Loading the .ui file from the resources
self.ui = uic.loadUi(context.get_resource("mainwindow.ui"), self)
# Binding the button to the print_data function defined in logic.py
self.main_button.clicked.connect(print_data)
Content of logic.py
:
import json
def print_data():
# Getting the resource data filepath
filepath = "../resources/base/static_data.json"
# Processing the resource file
with open(filepath) as file:
data = json.load(file)
print(data["message"])
One possible solution is to create the context in a file where everyone can access that variable:
base.py
Then it is used in the other classes:
gui.py
logic.py
main.py