【问题标题】:Can't find SpaCy model when packaging with PyInstaller使用 PyInstaller 打包时找不到 SpaCy 模型
【发布时间】:2021-07-17 13:27:23
【问题描述】:

我正在使用 PyInstaller 将 python 脚本打包成 .exe。该脚本使用 spacy 加载以下模型:en_core_web_sm。我已经运行python -m spacy download en_core_web_sm 将模型下载到本地。问题是当 PyInstaller 尝试打包我的脚本时,它找不到模型。我收到以下错误:Can't find model 'en_core_web_sm'. It doesn't seem to be a Python package or a valid path to a data directory. 我想这可能意味着我需要在我的 python 脚本中运行下载命令以确保它具有模型,但如果我让我的脚本下载模型,它只会说明要求已经很满足了。我还有一个处理引入隐藏导入的钩子文件,并且应该也引入模型:

from PyInstaller.utils.hooks import collect_all, collect_data_files

datas = []
datas.extend(collect_data_files('en_core_web_sm'))

# ----------------------------- SPACY -----------------------------
data = collect_all('spacy')

datas.extend(data[0])
binaries = data[1]
hiddenimports = data[2]

# ----------------------------- THINC -----------------------------
data = collect_all('thinc')

datas.extend(data[0])
binaries += data[1]
hiddenimports += data[2]

# ----------------------------- CYMEM -----------------------------
data = collect_all('cymem')

datas.extend(data[0])
binaries += data[1]
hiddenimports += data[2]

# ----------------------------- PRESHED -----------------------------
data = collect_all('preshed')

datas.extend(data[0])
binaries += data[1]
hiddenimports += data[2]

# ----------------------------- BLIS -----------------------------

data = collect_all('blis')

datas.extend(data[0])
binaries += data[1]
hiddenimports += data[2]

# ----------------------------- STDNUM -----------------------------

data = collect_all('stdnum')

datas.extend(data[0])
binaries += data[1]
hiddenimports += data[2]

# ----------------------------- OTHER -------------------------------

hiddenimports += ['srsly.msgpack.util']

我使用以下代码下载模型,然后用 PyInstaller 打包脚本:

os.system('python -m spacy download en_core_web_sm')
PyInstaller.__main__.run([path_to_script, '--onefile', '--additional-hooks-dir=.'])

hook-spacy.py 脚本与 PyInstaller 正在打包的脚本位于同一目录中。

如果我在本地运行脚本,所有这些都有效。它会找到应有的模型。如果我尝试使用 PyInstaller 打包脚本并尝试运行 .exe,我只会收到此错误。

我正在使用 Python v3.8.7、PyInstaller v4.2 和 spacy v3.0.3 与 en_core_web_sm v3.0.0

【问题讨论】:

标签: python pyinstaller spacy


【解决方案1】:

当您像这里一样使用 PyInstaller 将数据文件收集到包中时,这些文件实际上会编译成生成的 exe 本身。在评估 import 语句时,PyInstaller 会透明地处理 Python 代码。

但是,对于数据文件,您必须自己处理。例如,spacy 可能正在当前工作目录中寻找模型。它不会找到您的模型,因为它被编译到 .exe 中,因此不存在于当前工作目录中。

您将需要使用此 API:

https://pyinstaller.readthedocs.io/en/stable/spec-files.html#using-data-files-from-a-module

这允许您从 PyInstaller 创建的 exe 中读取数据文件。然后你可以将它写入当前工作目录,然后 spacy 应该能够找到它。

【讨论】:

  • 所以文档看起来这是获取模型的方法:pkgutil.get_data('en_ore_web_sm', 'en_core_web_sm-3.0.0\\ner\\model')。这看起来对你吗?如果是这样,我还不清楚我当时在 spacy.load() 函数中调用了什么,因为 pkgutil.get_data() 似乎在加载函数需要路径时向我返回了一个二进制对象。
  • 我不确定这是否是正确的调用参数,但如果它返回一个二进制对象,它们可能是好的。最简单的做法就是将返回的二进制数据写入当前工作目录下名为en_ore_web_sm的文件中,然后正常调用spacy。
  • 我不能通过不为 PyInstaller 指定 --onefile 参数来解决这个问题吗?这应该会在与 .exe 相同的目录中创建必要的文件。
  • 我认为是这样,但我相信您需要将文件视为“二进制”而不是“数据”以避免打包。
  • 我删除了--onefile 参数,事情正在取得进展。我现在在我的 exe 中获取站点包位置时遇到问题。我正在导入 site 并调用 getsitepackages() 但我收到以下错误:module 'site' has no attribute 'getsitepackages'
猜你喜欢
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 2022-01-02
  • 1970-01-01
  • 2019-10-11
  • 1970-01-01
相关资源
最近更新 更多