1

我正在尝试通过利用 Pythons namespace packages将一个大的(几乎是整体的)Python 项目拆分为多个部分。因此,我将文件解析器提取*.rules命名空间包中。Python 将此称为分布

我遵循了该指南,据我所知它部分有效,但是......

简而言之:在主项目中,单独分布的命名空间包的命名空间是不可见的,因为包搜索首先找到本地包,并不会与来自 的系统包合并site-packages

项目结构

这是我的目录/包和模块结构的一部分。

主要项目:

pyIPCMI/                  # Git repository root
  pyIPCMI/
    __init__.py
    Common/
      __init__.py
      File1.py
    Compiler/
      __init__.py
      Vendor1.py
      Vendor2.py
  setup.py

规则解析器的分布

pyIPCMI.Parser.Rules/     # Git repository root
  pyIPCMI/
    Parser/
      Rules/
        __init__.py
        Parser.py
  setup.py

包说明(安装工具)

主项目是这样打包的:

import setuptools

setuptools.setup(
  name="pyIPCMI",
  version="1.1.5",
  author="Paebbels",
  author_email="abc@xyz.de",
  description="",
  long_description="",
  url="https://github.com/Paebbels/pyIPCMI",

  packages=setuptools.find_packages(),

  classifiers=["License :: OSI Approved :: Apache Software License"],
  python_requires='>=3.5',
  install_requires=[],
)

嵌入的命名空间是这样打包的:

import setuptools

namespace =   ["pyIPCMI", "Parser", "Rules"]

setuptools.setup(
  name=".".join(namespace),
  version="1.1.4",
  author="Paebbels",
  author_email="abc@xyz.de",
  description="",
  long_description="",
  url="https://github.com/Paebbels/pyIPCMI.Parser.Rules",

  packages=setuptools.find_namespace_packages(
    include=[".".join(namespace), ".".join(namespace) + ".*"]
  ),
  namespace_packages=namespace[0:1],

  classifiers=["License :: OSI Approved :: Apache Software License"],
  python_requires='>=3.5',
  install_requires=[],
)

所有发行版都是:

  • setuptools使用 Travis-CI打包
  • 部署到 PyPI,然后
  • 使用 .安装在本地计算机上pip

PyPI 的命名空间结构

pyIPCMI
pyIPCMI.Parser.Files
pyIPCMI.Parser.Rules
pyIPCMI.Toolchains
pyIPCMI.Toolchains.Vendor1
pyIPCMI.Toolchains.Vendor2

问题描述

在使用 PyCharm 等主项目进行开发时,本地找到的命名空间优先于来自site-packages. 此外,这些命名空间不会被合并。因为主项目具有相同的根名称空间pyIPCMI,所以在本地开发项目中继续搜索,但不搜索site-packages

知道如何开发主要项目吗?


请告知需要什么信息来解决这个问题。我试图写下我目前掌握的所有信息。但是这个问题可能需要改进才能得到解决方案。

4

2 回答 2

0

据我所知,命名空间包必须是空的,并且在所有已安装的项目中都是如此。

显然你的pyIPCMI项目有一个顶级的non-namespace-package pyIPCMI,即你有一个pyIPCMI/__init__.py文件。所以我认为你不能pyIPCMI在其他项目中拥有命名空间包。如果您想成为其他项目中的名称空间包,我会尝试删除此pyIPCMI/__init__.py文件(并将其设为名称空间包) 。pyIPCMI

于 2019-10-13T22:05:08.643 回答
0

我上周遇到了同样的问题并找到了解决方案。作为第一个例子,让我给你我的初始(非工作)布局。

目录结构 1(插件尚未提取)

project-dir
  +-- pyproject.toml/setup.py
  +-- myproject
        +-- __init__.py
        +-- app.py
        +-- plugins
              +-- __init__.py
              +-- plugin1
                    +-- __init__.py
                    +-- plugmodule.py
              +-- plugin2
                    +-- __init__.py
                    +-- plugmodule.py

应用程序已经有代码可以根据这种结构查找插件模块。在写这篇文章时,我最初的理解是我可以通过创建具有以下结构的 Python 包来提供额外的插件:

plugin-package-dir
  +-- pyproject.toml/setup.py
  +-- myproject
        +-- plugins
              +-- plugin3
                    +-- __init__.py
                    +-- plugmodule.py

如官方文档中所述,命名空间包不包含 __init__.py此处的文件。

但这没有用

解决方案

为了完成这项工作,我需要将“插件”包从主项目子树中完全提取出来,并将其设为纯名称空间包。然后需要手动将这个新包添加到您的setup.py/pyproject.toml因为默认包发现无法识别它。

我最终得到了以下结构:

project-dir
  +-- pyproject.toml/setup.py
  +-- myproject
        +-- __init__.py
        +-- app.py
  +-- myproject_plugins
        +-- plugins
              +-- plugin1
                    +-- __init__.py  # <-- not strictly needed? (see note)
                    +-- plugmodule.py
              +-- plugin2
                    +-- __init__.py  # <-- not strictly needed? (see note)
                    +-- plugmodule.py

然后对于插件包,我有这个:

plugin-package-dir
  +-- pyproject.toml/setup.py
  +-- myproject_plugins
        +-- plugins
              +-- plugin3
                    +-- plugmodule.py
              +-- plugin4
                    +-- plugmodule.py

注意__init__.py由于我加载插件的方式,这些文件存在于主项目插件中。为了迭代命名空间,我在插件发现期间将其导入。相反,我可以捕获ImportError并报告根本没有找到插件。

如果我可以删除__init__.py并捕获导入错误,我还没有调查 100%。我已经在这方面浪费了太多时间,不想破坏现在正在工作的东西;)

于 2021-02-08T06:47:12.733 回答