假设您有一个名为Ninja的大型(python)软件项目.项目的几个部分如服务器和客户端,还有一个通用的基础结构库,它包含公共类和工具.当然我会创建一个像这样的包结构:ninja.core,ninja.server和ninja.client,其中服务器和客户端都以某种方式导入ninja.core.出于开发目的(我们将eclipse与Subversion一起使用),核心,服务器和客户端都在不同的项目中进行维护,从而产生如下文件夹结构:
eclipse_workspace
|
>-Ninja_core
| |
| >-ninja
| |
| >-core
|
>-Ninja_client
| |
| >-ninja
| |
| >-client
.
.
.
有一个java背景我认为这是可能的,但事实证明(读:导入错误)这不起作用.正如在this answer中所指出的,通常不可能同时拥有ninja.core和ninja.client,除非它们是同一个包ninja的子包,它们不是.这导致:
方法A:
>将整个代码放在一个eclipse / svn项目中,只有一个
包ninja与相应的子包.
在生产环境中,我们希望能够安装核心和服务器,但不能安装客户端或核心和客户端,而不能安装服务器.我可能会弄错,但就我理解python包而言,使用方法A是不可能的.保持项目分离但兼容,使用名称为ninja_core,ninja_client和ninja_server的包似乎很有用.事实上解决了导入问题,并且在开发设置中一切都运行顺畅.为了满足能够独立安装服务器和客户端的要求,我提出了以下想法:
方法B:
>创建一个名为ninja的新项目,其中包含ninja包
>让忍者的__init__.py导入其他库(如果已安装),使它们看起来像是在忍者内部.
到目前为止,我还没有这个工作,我认为甚至可能无法实现.我在考虑这样的事情:
# __init__.py of ninja
import ninja_core as core
# or this:
from ninja_core import core
# or this:
import ninja_core.core
我尝试了这些并再次导致导入错误.谷歌搜索结合python包的方法,而不是找到任何与我的问题相关的东西后,我来到这里.
我在想,也许整个事情都是设计错误.如果客户端和服务器可以独立安装,那么它们是否应该在同一个包中?想要能够独立安装客户端和服务器是一个坏主意吗?为什么我可以在java中扩展包,但不能在python中扩展?这背后的想法是什么?
TL;博士
我正在开发Ninja库,用户应该能够导入ninja.client并导入ninja.server.需要可以单独为客户端和服务器安装库.如何实现这一目标?
最佳答案
如果你将顶层命名空间ninja留空,那么Python 3.3及更高版本已经支持了这一点,参见PEP 420;您所要做的就是创建ninja目录并省略该目录中的__init__.py文件:
eclipse_workspace
|
>-Ninja_core
| |
| >-ninja
| |
| >-core
| |
| >-__init__.py
|
>-Ninja_client
| |
| >-ninja
| |
| >-client
| |
| >-__init__.py
除了子核心和客户端目录之外,忍者目录仍然是空的.这些目录有__init__.py文件.
在早期的Python版本中,您可以使用setuptools
namespace packages添加对命名空间的支持.Zope和Plone项目已使用setuptools多年来发布命名空间包.
基本原则是确保您的项目是包含setup.py文件的包,并且安装在development mode中或作为最终产品安装.你的忍者目录确实有一个__init__.py文件,但这些只包含以下行:
__import__('pkg_resources').declare_namespace(__name__)
并且每个项目的setup.py文件必须声明命名空间:
setup(
# ...
namespace_packages = ['ninja']
)