简体   繁体   English

如何为python包创建嵌套的包空间?

[英]How to create a nested package space for python packages?

I'm restructuring the python libraries our company is developing into various groups. 我正在将我们公司正在开发的python库进行重组。 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. 为了避免污染顶层模块名称空间,我想将所有内容归入顶层“ companyname”包中,因此我们将使用“ coname.utils”,“ coname.qa”,“ coname.api”等。 。 Several of these are expected to be distributed with our product, or publicly installable. 其中一些有望与我们的产品一起分发或可以公开安装。 'qa' will be purely internal. “ qa”将完全是内部的。

Google does something similar. Google做了类似的事情。 Eg, the protobuf library is available as "google.protobuf" in the module path. 例如,protobuf库在模块路径中以“ google.protobuf”的形式提供。 However, it's not particularly clean: the .pth file installed by the protobuf package looks like this: 但是,它并不是特别干净:protobuf软件包安装的.pth文件如下所示:

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. 我认为这样做是为了欺骗导入引擎,因为“ google”目录中没有__init__.py。 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. 我不介意使任何“ coname- *”包都需要“ coname-top”包才能将__init__.py放入其中。 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. 我还不确定如何说服setuptools将软件包视为不在模块树的顶部,或者是否有可能从一棵树中创建子软件包。

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. 为了明确起见,我专门询问如何设置上述内容,以便例如可以与coname-api分开分发和安装coname-qa。 It is reasonable that both would depend on coname-tools. 两者都依赖于同名工具是合理的。

  1. The directory a needs to be a package. 目录a必须是一个包。 Add an __init__.py file to make it a package, which is a step up from being a simple directory. 添加一个__init__.py文件使其成为一个包,这比从简单目录迈进了一步。

  2. The directory b also needs to be a subpackage of a. 目录b还必须是a的子包。 Add an __init__.py file. 添加__init__.py文件。

  3. 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. 通常,将Python模块的每个目录都作为正式包是一个好主意。

  4. In order to import, the package needs to be on sys.path; 为了导入,该程序包需要在sys.path上。 this is built from the PYTHONPATH environment variable. 这是从PYTHONPATH环境变量构建的。 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. 这意味着必须安装a,或者您当前的工作目录还必须是a上一级的软件包。

OR, you need to set your PYTHONPATH environment variable to include a. 或者,您需要将PYTHONPATH环境变量设置为包含a。

What you are trying to do is create a namespace package. 您试图做的是创建一个名称空间包。 You can use setuptools to accomplish this. 您可以使用setuptools完成此操作。

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

Set up a directory structured like this: 设置目录结构如下:

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

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

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

There are a few variations, depending on what tools you intend to use for deployment. 根据您打算使用哪种工具进行部署,会有一些变化。 You can look at the link above for details on that. 您可以查看上面的链接以获取有关此信息的详细信息。

This directory structure segregates the portions of your namespace that you want to be separately installable. 此目录结构隔离了您希望单独安装的名称空间部分。 You can also version the different subpackages separately, which can be nice for maintenance. 您还可以分别对不同的子软件包进行版本控制,这对于维护非常有用。 Presumably you might have dependencies between some of your subpackages. 大概您的某些子包之间可能存在依赖关系。 You might add code to one subpackage that relies on api members in another subpackage that only exist in some versions of that subpackage. 您可以将代码添加到依赖于另一个子包中的api成员的一个子包中,该子包仅存在于该子包的某些版本中。 In the setup.py files you can define what versions of dependencies are required. 在setup.py文件中,您可以定义所需版本的依赖项。

See setuptools documentation for details on how to write the setup.py 有关如何编写setup.py的详细信息,请参见setuptools文档

Once you have this set up, you should be able to build your project with setuptools and you can separately install utils, qa, api, etc. Once installed in an environment, you can import them with "import coname.utils", "import coname.qa", etc. 设置完成后,您应该可以使用setuptools构建项目,并且可以分别安装utils,qa,api等。在环境中安装后,可以使用“ import coname.utils”,“ import”导入它们。 coname.qa”,等等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM