Pyinstaller-包含以编程方式导入的模块

时间:2019-12-03 15:06:18

标签: python python-3.x 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'),
 ]

但这似乎不是一个很好的解决方案-即,我将向最终用户发送代码。

1 个答案:

答案 0 :(得分:1)

这不是答案,但这是我可以显示一些代码的唯一方法-这是我的包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 .py中的globals()['__loader__'].toc中显示为例如"mypkg.file1"为True时,模块mypkg \ file1.py的sys.frozen

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