Skip to main content

Python resource manager to work with the standard library for regular python code and executables.

Project description

Standard Resource Functions

  • files - importlib.resources files this function is the standard for retrieving resources for Python 3.9+

  • as_file - context manager for retrieving a true filepath for Python 3.9+.

  • read_binary - Return the bytes found in the package with the given basename.

  • read_text - Return the text found in the pakcage with the given basename.

  • contents - Return an iterable of basenames in the given package.

  • is_resource - Return if the given package, basename exists.

Custom Helpers
  • register - Register a package and basename to an identifier. This can be overridden and used like a theme.

  • has_resource - Return if the given identifier has a registered resource.

  • get_resources - Return a dictionary of {identifier: Resource(package, name)}

  • get_resource - Return the Resource object for the given identifier, fallback, or default value.

  • get_binary - Return the binary data read from the found resource.

  • get_text - Return the text data read from teh found resource.

Resource Man Example

Register and use identifiers.

# mylib/run.py
# File Structure:
#     mylib/
#         __init__.py
#         run.py
#         actions/
#             __init__.py
#             edit-cut.png
import resource_man

resource_man.register('edit-cut', 'mylib.actions', 'edit-cut.png')

if __name__ == '__main__':
    edit_cut_bin = resource_man.get_binary('edit-cut')

Qt Example

The importlib.resources library prefers reading data from a resource instead of using filename paths. This is to speed up execution and support with zip files. The resource_man library includes a QIcon. This QIcon can take in binary data as the first argument to create the icon. This QIcon can also be created using fromTheme with a registered resource. This library uses QtPy to support PySide or PyQt.

# mylib/run.py
# File Structure:
#     mylib/
#         __init__.py
#         run.py
#         actions/
#             __init__.py
#             edit-cut.png
import my_lib.actions  # Must import packages with subpackages that use importlib.resources
from qtpy import QtWidgets
from resource_man.qt import QIcon, register, get_binary, read_binary


# Register package resources to an identifier that can be used with fromTheme
# must import check_lib.check_sub for importlib.resources to work
register('edit-cut', 'my_lib.actions', 'edit-cut.png')


if __name__ == '__main__':
    app = QtWidgets.QApplication([])

    widg = QtWidgets.QWidget()
    widg.setLayout(QtWidgets.QVBoxLayout())
    widg.show()

    # Get icon from theme (resource_man register support)
    btn_theme = QtWidgets.QPushButton(QIcon.fromTheme('edit-cut'), 'Theme')
    widg.layout().addWidget(btn_theme)

    # resource_man binary
    btn_binary_resource_man = QtWidgets.QPushButton(QIcon(get_binary('edit-cut')), 'Binary resource_man')
    widg.layout().addWidget(btn_binary_resource_man)

    # importlib.resources binary
    btn_binary_importlib = QtWidgets.QPushButton(QIcon(read_binary('my_lib.actions', 'edit-cut.png')), 'importlib resource_man')
    widg.layout().addWidget(btn_binary_importlib)

    app.exec_()

importlib.resources Example

Using filenames and paths. As stated earlier Python recommends that you use importlib.resources to read the resource data. Filenames still have some support with importlib.resources, but it with the use of context manager.

# my_interface.py
# sdl2 with sld2.dll in package
# File Structure:
#     my_sdl/
#         sdl2_dll_path/
#             SDL2.dll
#         __init__.py
#         my_interface.py
import os
from resource_man import files, as_file

with as_file(files('my_sdl').joinpath('sdl2_dll_path/SDL2.dll')) as sdl_path:
    os.environ.setdefault('PYSDL2_DLL_PATH', os.path.dirname(str(sdl_path)))
    import sdl2

# Use sdl2
assert sdl2 is not None

PyInstaller Helper

This library has a collect_datas helper function. I believe this function to be more useful than PyInstallers built in tool.

# hook-mylib.py
#
# File Structure:
#     mylib/
#         __init__.py
#         run.py
#         edit-cut.png
#     pyinstaller-hooks/
#         hook-mylib.py
from resource_man.pyinstaller import collect_datas

datas = collect_datas('mylib')  # Will also find resources in sub packages

Use the pyinstaller helper with pylibimp to import all resources for your project.

# build_exe.py
#
# File Structure:
#     mylib/
#         __init__.py
#         run.py
#         edit-cut.png
#     build_exe.py
from resource_man.pyinstaller import collect_datas
from PyInstaller import config
from pylibimp import import_module
import subprocess


def get_dependent_modules(main_module):
    """Get the dependent modules from importing the main_module."""
    dependent_modules = {}
    import_module(main_module, reset_modules=True, dependent_modules=dependent_modules)
    return dependent_modules


def get_datas(dependent_modules):
    """Return a list of command line arguments for pyinstaller to add data."""
    pyinstaller_args = []
    ignore_pkgs = ['PySide', 'PyQt', 'shiboken']  # PyInstaller properly includes resources for these
    for name in list(dependent_modules.keys()):
        if '.' in name:
            name = name.split('.', 1)[0]
        if name in ignore_pkgs:
            continue
        ignore_pkgs.append(name)
        with contextlib.suppress(ImportError, TypeError, ValueError, IndexError, Exception):
            datas = collect_datas(name)
            for data in datas:
                pyinstaller_args.extend(['--add-data', os.pathsep.join(data)])

    return pyinstaller_args


if __name__ == '__main__':
    main_module = 'mylib/run.py'
    modules = get_dependent_modules(main_module)
    args = get_datas(modules)

    subprocess.run(['pyinstaller', main_module] + args)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

resource_man-1.0.0.tar.gz (10.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

resource_man-1.0.0-py3-none-any.whl (17.9 kB view details)

Uploaded Python 3

File details

Details for the file resource_man-1.0.0.tar.gz.

File metadata

  • Download URL: resource_man-1.0.0.tar.gz
  • Upload date:
  • Size: 10.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.6.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.61.2 CPython/3.9.0

File hashes

Hashes for resource_man-1.0.0.tar.gz
Algorithm Hash digest
SHA256 631ed280522b9361527317430ffde91eaf2bc97b52bed433513e42cdf1967094
MD5 1ddb66121569ddea67822d30a9cc5df8
BLAKE2b-256 e26203639864bc597550bbd86b60c77a2e1beb2d00cadff70e06dd262db7f9b4

See more details on using hashes here.

File details

Details for the file resource_man-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: resource_man-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 17.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.6.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.61.2 CPython/3.9.0

File hashes

Hashes for resource_man-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b8b44c8d10d83bf54cdc81e1b002a68f6f9cd7877cbceb8e7ccf2a72f6dfd8d5
MD5 ec3bdfa64cdb65afa3b5f38d2b352f80
BLAKE2b-256 7a40b50e1cf93c8abe1e151b5d1485c2da5e540a627e1c9fa7fc72fddea07ab3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page