Skip to content

Qt Resources Pipeline

This guide explains the end-to-end Qt resource pipeline: what init() generates, how to use AppIcons and AppImages, and how to customize the output directory.


What init() Generates

When you call init(), the bootstrap sequence compiles Qt resources and writes three Python modules into bin/ (or your custom bin_path):

File Purpose
bin/resources_rc.py Compiled Qt resource module — registers :/icons/ and :/images/ with the Qt resource system
bin/app_icons.py Auto-generated class AppIcons — one attribute per icon
bin/app_images.py Auto-generated class AppImages — one attribute per image

These files are generated from the .qrc source bundled with the package and from any custom assets you add to bin/themes/. They are created or overwritten each time init() runs with the resource build step enabled (the default).


Resource Path Format

All Qt resource paths use a single prefix segment:

:/icons/<filename>.png
:/images/<filename>.jpg

Old double-prefix paths are invalid

Prior versions emitted paths like :/icons/icons/cil-3d.png. This was a bug. The correct format is :/icons/cil-3d.png. Update any hard-coded paths in your QSS files or Python code accordingly.


Using AppIcons and AppImages

AppIcons and AppImages are module-level variables exported from ezqt_app.shared.resources. They are None at import time and populated by init() via load_runtime_rc().

Correct import pattern

Always call init() before accessing these symbols:

from ezqt_app import init
from ezqt_app.shared.resources import AppIcons, AppImages

init()  # populates AppIcons and AppImages

icon_path = AppIcons.cil_home          # ":/icons/cil-home.png"
logo_path = AppImages.logo_placeholder # ":/images/logo-placeholder.jpg"

When the import happens before init()

If you import AppIcons at the top of a module that is loaded before init() runs, you capture the initial None value. The variable in the outer module is never updated because Python binds the name to the object at import time:

# top_level_module.py — loaded before init() is called
from ezqt_app.shared.resources import AppIcons  # AppIcons is None here

init()  # too late — AppIcons in this module is still None
print(AppIcons.cil_home)  # AttributeError: 'NoneType' object has no attribute 'cil_home'

Use one of these safe patterns instead:

    from ezqt_app.shared import resources

    init()
    icon_path = resources.AppIcons.cil_home  # resolved at access time, always live
    from ezqt_app import init

    init()

    from ezqt_app.shared.resources import AppIcons  # safe — init() already ran
    icon_path = AppIcons.cil_home

What Is No Longer in the QRC

Starting from this version, config/ and translations/ are no longer embedded in resources_rc.py. Those assets are read directly from the filesystem at runtime.

This reduces the compiled resource size and avoids stale embedded copies diverging from the user's project files.


Custom bin_path

By default init() writes all generated assets to <project_root>/bin/. Pass bin_path to choose a different directory:

from ezqt_app import init

# Relative path — resolved against project_root (defaults to Path.cwd())
init(bin_path="binaries")

# Absolute path
from pathlib import Path
init(bin_path=Path("/opt/myapp/assets"))

The bin_path value is forwarded to InitOptions.bin_path and resolved in InitOptions.resolve(). Relative values are made absolute by joining them with project_root.

Note

When using a custom bin_path, make sure your application code and load_runtime_rc() can locate the generated files. The path is stored in the runtime path registry and used automatically by the bootstrap sequence, but any hard-coded bin/ references in your own code will need updating.


ResourceCompilationError

If pyside6-rcc is not available on PATH when init() runs, a ResourceCompilationError is raised immediately instead of silently producing an empty or broken resource module:

ezqt_app.domain.errors.ResourceCompilationError: pyside6-rcc not found

This is an explicit failure — it prevents the application from starting with broken Qt resources. See the Troubleshooting section in Getting Started for the fix.


How load_runtime_rc() Works

The bootstrap sequence calls load_runtime_rc() after QRC compilation. This function:

  1. Reloads bin/resources_rc.py into sys.modules, registering all Qt resources with the Qt resource system.
  2. Loads bin/app_icons.py and assigns its AppIcons class to ezqt_app.shared.resources.AppIcons.
  3. Loads bin/app_images.py and assigns its AppImages class to ezqt_app.shared.resources.AppImages.

You do not need to call load_runtime_rc() manually — it is invoked automatically as part of init().


See Also