当你的包被别人导入时,如何让pyInstaller找到数据文件



作为iapws包的用户,我遇到了一个我无法解决的普遍问题。这个包很小,也是一个不错的候选者。

下面是一个简单的脚本(我称之为main.py):
from iapws import IAPWS97
def main():
h = IAPWS97(P=1, x=1).h
print(f"h = {h:.5g} kJ/kg")
if __name__ == "__main__":
main()

这个脚本工作正常。通过pyinstaller main.py打包创建distmain文件夹,main.exe在里面。执行main.exe产生

Traceback (most recent call last):
File "main.py", line 3, in <module>
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "PyInstallerloaderpyimod03_importers.py", line 531, in exec_module
File "iapws__init__.py", line 15, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'C:\...\dist\main\iapws\VERSION'
[22492] Failed to execute script main

这里的问题是缺少VERSION文件,即iapws包的数据文件,我作为导入包的打包者不应该为此烦恼。我克隆了iapws包,并试图以几种方式在setup.py中指定VERSION数据文件,但pyInstaller没有选择它。

如何在iapws包内指定以触发pyInstaller拾取此类数据文件?

此问题已与iapws开发人员进行了沟通。

为此,pyInstaller允许应用钩子。在本例中,创建一个名为hook-iapws.py的钩子,内容为

from PyInstaller.utils.hooks import collect_data_files
datas = collect_data_files('iapws')

作为用户在包中,通过指向pyinstaller specfile中的包含目录来找到钩子:

a = Analysis(...
hookspath=["pyinstaller-hooks"],
...)

作为开发人员在包中,可以通过pyInstaller找到钩子,如本链接所述,也可以将钩子文件提供给pyInstaller开发人员。

我在另一个线程上回答,但同样适用于这里:

您需要强制pyinstaller包含iapws文件,因为它似乎在生成适当的钩子时存在问题。

pyinstaller "your_script.py" --collect-all iapws

我在这里回顾了一些有帮助的命令选项:https://pyinstaller.org/en/stable/usage.html

最新更新