I have a package that sort of looks like this:
- package
-- module1.py
-- module2.py
-- __init__.py
In init.py I am programmatically scanning the package and importing the modules that are inside.
import importlib
import pkgutil
registry = {}
def creatable(cls):
if cls.handles_type() in registry:
raise KeyError("Duplicate string representations found for string: " + cls.handles_type())
registry[cls.handles_type()] = cls
return cls
def import_submodules(package, recursive=False):
""" Import all submodules of a module, recursively, including subpackages
"""
if isinstance(package, str):
package = importlib.import_module(package)
results = {}
for loader, name, is_pkg in pkgutil.walk_packages(package.__path__):
full_name = package.__name__ + '.' + name
results[full_name] = importlib.import_module(full_name)
if recursive and is_pkg:
results.update(import_submodules(full_name))
return results
import_submodules(__name__)
Inside the modules, there are classes annotated with the @creatable decorator that I define here. The idea is to have a registry dictionary with the key being the class name and the value being the class (so I can create instances using the string representation).
The issue is, the registry is empty when using Pyinstaller.
UPDATE:
The issue is that package.__path__
does not contain anything. It can be fixed by adding the .py files on the package path i.e.
datas=[
('package/*.py', 'package'),
]
But this doesn't look like a good solution - i.e. I'd be sending code to the end user.