不同项目的python库如何在同一个包中?

Apl*_*nus 5 python import package

假设您有一个名为Ninja的大型(python)软件项目.项目的几个部分如服务器客户端,还有一个通用的基础结构库,它包含公共类和工具.当然,我会创建一个这样的包结构:ninja.core,ninja.server并且ninja.client,服务器客户端都ninja.core以某种方式导入.出于开发目的(我们将eclipse与Subversion一起使用),核心,服务器客户端都在不同的项目中进行维护,从而产生如下文件夹结构:

eclipse_workspace
|
>-Ninja_core
| |
| >-ninja
|   |
|   >-core
|
>-Ninja_client
| |
| >-ninja
|   |
|   >-client
.
.
.
Run Code Online (Sandbox Code Playgroud)

有一个java背景我认为这是可能的,但事实证明(读:导入错误)这不起作用.正如在这个答案中所指出的,通常不可能同时具有这两者ninja.core,ninja.client 除非它们是同一包装的子包装ninja,否则它们不是.这导致:

方法A:

  • 将整个代码放在一个eclipse/svn项目中,并且只有一个包含ninja相应子包的包.

在生产环境中,我们希望能够安装核心服务器,但不能安装客户端核心客户端,而不能安装服务器.我可能会弄错,但就我理解python包而言,使用方法A是不可能的.保持项目分离但兼容,使用具有名称的包似乎很有用ninja_core,ninja_client并且ninja_server实际上解决了导入问题并使开发设置中的一切运行顺利.为了满足能够独立安装服务器客户端的要求,我提出了以下想法:

方法B:

  • 创建一个名为ninja的新项目,其中包含该包ninja
  • __init__.pyninja进口的其他库(如果已安装)的方式,他们似乎在里面ninja.

到目前为止,我还没有这个工作,我认为甚至可能无法实现.我在考虑这样的事情:

# __init__.py of ninja
import ninja_core as core
# or this:
from ninja_core import core
# or this:
import ninja_core.core
Run Code Online (Sandbox Code Playgroud)

我尝试了这些并再次导致导入错误.谷歌搜索结合python包的方法,而不是找到任何与我的问题相关的东西后,我来到这里.

我在想,也许整个事情都是设计错误.如果客户端服务器可以独立安装,那么它们是否应该在同一个包中?想要能够独立安装客户端和服务器是一个坏主意吗?为什么我可以在java中扩展包,但不能在python中扩展?这背后的想法是什么?

TL;博士

我正在开发的忍者图书馆,用户应该能够做import ninja.clientimport ninja.server.需要可以单独为客户端服务器安装库.如何实现这一目标?

Mar*_*ers 4

如果您将顶级命名空间留空ninja,Python 3.3 及更高版本中已原生支持此功能,请参阅PEP 420;您所要做的就是创建ninja目录并忽略__init__.py该目录中的文件

eclipse_workspace
|
>-Ninja_core
| |
| >-ninja
|   |
|   >-core
|       |
|       >-__init__.py
|
>-Ninja_client
| |
| >-ninja
|   |
|   >-client
|       |
|       >-__init__.py
Run Code Online (Sandbox Code Playgroud)

ninja除了子目录core和目录之外,目录保持为空client。这些目录确实__init__.py文件。

在早期的 Python 版本中,您可以使用setuptools命名空间包添加对命名空间的支持。Zope 和 Plone 项目setuptools多年来一直在发布命名空​​间包。

基本原则是确保您的项目是带有文件的包,并且以开发模式setup.py安装或作为最终产品安装。您的目录确实有一个文件,但这些文件必须仅包含以下行:ninja__init__.py

__import__('pkg_resources').declare_namespace(__name__)
Run Code Online (Sandbox Code Playgroud)

每个项目的文件setup.py必须声明名称空间:

setup(
    # ...
    namespace_packages = ['ninja']
)
Run Code Online (Sandbox Code Playgroud)