Pyinstaller语言 - 包括以编程方式导入的模块



>我有一个包,看起来像这样:

- package
-- module1.py
-- module2.py
-- __init__.py

init.py 我正在以编程方式扫描包并导入其中的模块。

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__)

在模块内部,有一些类用我在这里定义的@creatable装饰器进行注释。这个想法是拥有一个注册表字典,其中键是类名,值是类(所以我可以使用字符串表示形式创建实例(。

问题是,使用Pyinstaller时注册表为空。

更新:

问题是package.__path__不包含任何东西。可以通过在包路径上添加.py文件来修复它,即

datas=[
('package/*.py', 'package'),
]

但这看起来不是一个好的解决方案 - 即我会向最终用户发送代码。

这不是答案,而是我可以显示一些代码的唯一方法 - 这是我的包 mypkg 的钩子文件,在钩子文件夹中,称为 hook-mypkg.py

import os
imports = []
for root, dirs, files in os.walk(os.path.join(os.getcwd(),"mypkg" )):
print(root)
for file in files:
if file.endswith( ".py") and not file.endswith( "__init__.py"):
print( "  ",file)
imports.append("mypkg."+file[:-3])
print( "........." )
print( "hi=",imports )
hiddenimports = imports

这绝对可以包含它在捆绑包中找到的.py文件 - 它们以init中的globals()['__loader__'].toc形式出现.py例如"mypkg.file1"模块 mypkg\file1.py 当sys.frozen为 True 时。

请注意,编辑钩子后,您必须删除 dist 并构建文件夹,然后重新运行 pyinstaller

最新更新