在外部库的命名空间中创建一个 Python 模块(自定义 spaCy 语言)

Creating a Python module in the namespace of an external library (custom spaCy language)

这个问题是在 spaCy v2 library 添加语言的上下文中,但它可能是一个通用的 python 包装问题。

在 spaCy 中,语言是 Language 基础 class 的子class,并且大部分工具都希望将给定的语言放置在规范命名的包中(例如spacy.lang.en 英文)。

有多种方法可以满足此要求(例如,@spacy.registry.languages),但这通常需要一些权衡(例如,您必须先导入一些代码来注册您的 classes,然后一切都很好,但是当您拥有自定义脚本、prodigy 食谱、库等工具时,这些工具不允许您“注入”自定义导入或有自己的方式这样做,这是行不通的 -或者通常容易出错)。如果有办法的话,我很乐意听到有关缓解此问题的建议。

所以我想我只要把我的语言放在 spaCy 期望的地方,就可以了。创建语言 subclass 是 documented enough.

所以我引导了一个库:

lib/
  src/
    spacy/
      lang/
        ka/ # example of a language that spaCy does not know about
          __init.py__ # my language subclass
  setup.py

init.py是一种简单的语言(简体):

import spacy
from spacy.language import Language


class GeorgianDefaults(Language.Defaults):

@spacy.registry.languages("ka")
class Georgian(Language):
    lang = "ka"
    Defaults = GeorgianDefaults

而我的 setup.py 是标准的,使用本地命名空间包:

setup(
    name="my-spacy-extras",
    packages=find_namespace_packages(where="src"),
    package_dir={"": "src"},
    install_requires=[
        "spacy>=2.3.0,<3.0.0"
    ]
)

我考虑过使用本机命名空间包,因为据我所知,这是针对此用例的现代方式。

但是当我打包代码时(或者实际上只是设置了一个 virtualenv 和 pip install -Ur requirements.txt 并且要求很简单 -e .),我得到了可怕的

ModuleNotFoundError: No module named 'spacy.lang.ka'

认为这是因为 spaCy 本身(参见 repo)不使用本地命名空间打包,但它既不使用 pkgutil 样式的包,我开始怀疑这是否可行。

那么,我是否有办法将我的自定义语言创建为一个模块,将其打包到一个库中,在 spacy 命名空间内(找不到更好的词)?

请务必遵循 spaCy v2 的 v2 文档,因为存在许多差异。 (注册表装饰器是 v3 中的新增功能)。

spaCy v2 支持自定义语言的入口点:https://v2.spacy.io/usage/saving-loading#entry-points

您的包将有自己的名称(不是 spacy),您可以通过在 setup.py 中的 spacy_languages 下添加入口点来在 spaCy v2 中添加自定义语言:

    entry_points={
        "spacy_languages": [
            "ka = spacy_lang_ka:Georgian",
        ]
    }

如果您的环境中安装了此软件包,那么 spacy.blank("ka") 应该可以找到并将此 class 加载为 Georgian(),而无需任何额外的步骤。同样,prodigy 应该能够将空白语言管道加载为 blank:ka.

spacy-stanza v0.2.5:

中显示了完整 setup.py 中的示例

https://github.com/explosion/spacy-stanza/blob/v0.2.5/setup.py