How to create a nested package space for python packages?

时间:2015-10-31 00:04:14

标签: python setuptools module-packaging

I'm restructuring the python libraries our company is developing into various groups. To avoid polluting the top level module namespace I'd like to group everything under a top level 'companyname' package, so we'll have 'coname.utils', 'coname.qa', 'coname.api', and so on. Several of these are expected to be distributed with our product, or publicly installable. 'qa' will be purely internal. Google does something similar. E.g., the protobuf library is available as "google.protobuf" in the module path. However, it's not particularly clean: the .pth file installed by the protobuf package looks like this: import sys, types, os;p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('google',));ie = os.path.exists(os.path.join(p,'__init__.py'));m = not ie and sys.modules.setdefault('google', types.ModuleType('google'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p) I think it does that to fool the import engine because there's no __init__.py in the "google" directory. But... not elegant. Is there a well established way of achieving this? I don't mind making any of the "coname-*" packages require a "coname-top" package just to get the __init__.py in there. I'm as-yet unsure how to convince setuptools to treat the package as not at the top of the module tree, nor if it's possible to create sub-packages from one tree. To clarify, I'm specifically asking how to set up the above so that coname-qa can be distributed and installed separately from coname-api, for example. It is reasonable that both would depend on coname-tools.

2 个答案:

答案 0 :(得分:1)

The directory a needs to be a package. Add an __init__.py file to make it a package, which is a step up from being a simple directory. The directory b also needs to be a subpackage of a. Add an __init__.pyfile. The directory test should probably also be a package. Hard to say if this is necessary or not. It's usually a good idea for every directory of Python modules to be a formal package. In order to import, the package needs to be on sys.path; this is built from the PYTHONPATH environment variable. By default the installed site-packages and the current working directory are (effectively) the only two places where a package can be found. That means that a must either be installed, or, your current working directory must also be a package one level above a. OR, you need to set your PYTHONPATH environment variable to include a.

答案 1 :(得分:0)

您要尝试做的是创建一个名称空间包。您可以使用setuptools完成此操作。

请参见https://packaging.python.org/guides/packaging-namespace-packages/#pkgutil-style-namespace-packages

设置目录结构如下:

coname-utils/
    setup.py
    coname/
        utils/
            __init__.py
            ...
        ...

coname-qa/
    setup.py
    coname/
        qa/
            __init__.py
            ...
        ...

coname-api/
    setup.py
    coname/
        api/
            __init__.py
            ...
        ...

有一些变体,具体取决于您打算使用哪种工具进行部署。您可以查看上面的链接以获取有关此信息的详细信息。

此目录结构隔离了您希望可单独安装的名称空间部分。您还可以分别对不同的子软件包进行版本控制,这对于维护非常有用。大概您的某些子包之间可能存在依赖关系。您可以将代码添加到依赖于另一个子包中的api成员的一个子包中,该子包仅存在于该子包的某些版本中。在setup.py文件中,您可以定义所需版本的依赖项。

有关如何编写setup.py的详细信息,请参见setuptools documentation

设置完成后,您应该可以使用setuptools构建项目,并且可以分别安装utils,qa,api等。在环境中安装后,可以使用“ import coname.utils”导入它们。 ,“导入coname.qa”等。