Python 我可以告诉PyInstaller打包我的整个源代码树吗?

Python 我可以告诉PyInstaller打包我的整个源代码树吗?,python,pyinstaller,python-3.5,Python,Pyinstaller,Python 3.5,当前我的PyInstaller规范如下所示: import sys import os import re from pathlib import Path DEBUG = True lib = Path("lib/alpha") hidden_imports = [] hidden_imports += lib.glob("processes/**/*.py") hidden_imports += lib.glob("ui/config_panels/**/*.py") hidden_i

当前我的PyInstaller规范如下所示:

import sys import os import re from pathlib import Path DEBUG = True lib = Path("lib/alpha") hidden_imports = [] hidden_imports += lib.glob("processes/**/*.py") hidden_imports += lib.glob("ui/config_panels/**/*.py") hidden_imports += lib.glob("ui/logic/**/*.py") hidden_imports = list(str(x) for x in hidden_imports) for index, path in enumerate(hidden_imports): path = re.sub(r"lib(\\|\/)", "", path) if "__init__.py" in path: path = re.sub(r"(\\|\/)__init__.py", "", path) else: path = re.sub(r"\.py", "", path) hidden_imports[index] = ".".join(re.split(r"\\|\/", path)) block_cipher = None a = Analysis( ["app.pyw"], pathex=["lib"], binaries=None, datas=[ ("icons/*", "icons") ], hiddenimports=hidden_imports, hookspath=None, runtime_hooks=None, excludes=None, win_no_prefer_redirects=None, win_private_assemblies=None, cipher=block_cipher ) pyz = PYZ( a.pure, a.zipped_data, cipher=block_cipher ) exe = EXE( pyz, a.scripts, a.binaries, a.zipfiles, a.datas, name="alpha", debug=DEBUG, strip=None, upx=True, console=DEBUG, icon="icons\\foo.ico" ) 导入系统 导入操作系统 进口稀土 从pathlib导入路径 调试=真 lib=路径(“lib/alpha”) 隐藏的_导入=[] 隐藏的\u导入+=lib.glob(“进程/***/*.py”) 隐藏的\u导入+=lib.glob(“ui/config\u panels/***/.py”) 隐藏的\u导入+=lib.glob(“ui/logic/***.py”) hidden_imports=列表(在hidden_imports中,str(x)代表x) 对于索引,枚举中的路径(隐藏的\u导入): path=re.sub(r“lib(\\\\\/),“”,path) 如果路径中有“\uuuu init\uuuuu.py”: path=re.sub(r“(\\\\\/)\uuuu init\uuuu.py“,”,path) 其他: path=re.sub(r“\.py”和“path”) 隐藏的导入[索引]=“.join(重新拆分(r“\\\\ \/”,路径)) 分组密码=无 a=分析( [“app.pyw”], pathex=[“lib”], 二进制文件=无, 数据=[ (“图标/*”,“图标”) ], hiddenimports=隐藏的\u导入, hookspath=无, 运行时挂钩=无, 排除=无, win\u no\u Preference\u重定向=无, win_private_Assembly=无, 密码=分组密码 ) pyz=pyz( a、 纯的,压缩的数据, 密码=分组密码 ) exe=exe( pyz, a、 剧本, a、 二进制文件, a、 拉链, a、 数据, name=“alpha”, 调试=调试, 条带=无, upx=真, 控制台=调试, icon=“icons\\foo.ico” ) 很丑,对吧

我的源代码树中有一些目录,其文件名遵循特定的命名约定,并使用
importlib
按需导入。出于明显的原因,我不想将所有这些模块的名称硬编码到我的规范中

当使用“hiddenimports”选项时,参数必须是模块名列表,因此我必须
glob
对于文件名,循环结果列表并“模块化”文件名,同时考虑到Windows和Linux支持


一定有更好的办法。有没有什么方法可以让PyInstaller只包含我的整个源代码树,即
lib/alpha
下的每个文件?

您可以使用包含整个目录树,但这并不能完全满足您的需要。因为您正在添加源文件,所以需要PyInstaller递归地分析它们以进行导入,以确保包含它们的所有依赖项。最好的方法是通过hiddenimports

我不想详细解释,我只想分享我自己的specfile中的一个片段,我用它来包含一些模块,这些模块不是我的应用程序直接包含的,而是提供给用户创建的插件使用的。这非常适合您的用例

# Files under mcedit2.synth are used only by plugins and not internally.
support_modules = []
for root, dirnames, filenames in os.walk(os.path.join('src', 'mcedit2', 'synth')):
    for filename in fnmatch.filter(filenames, '*.py'):
        if filename == "__init__.py":
            filepath = root
        else:
            filepath = os.path.join(root, filename)
            filepath = filepath[:-3]  # discard ".py"

        components = filepath.split(os.path.sep)
        components = components[1:]  # discard 'src/'

        if "test" in components or components == ["mcedit2", "main"]:
            continue

        modulename = ".".join(components)  # dotted modulename
        support_modules.append(modulename)

hiddenimports.extend(support_modules)

等一下。我想我可以使用
collect\u子模块
。hookfile通常使用它来收集导入库的子模块,但它也应该在specfile中可用。