分发命名空间包子模块

时间:2017-09-26 00:02:20

标签: python setuptools namespace-package

我已经将我的Python项目重组为同名伞。我的项目现在可以看作是多个子系统而不是相互依赖。这意味着现在可以单独分发每个子模块,以便只安装所需的依赖项。

旧结构:

/
├─ myproj/
│  ├─ __init__.py
│  ├─ mod1.py
│  ├─ subpackage1/
│  └─ subpackage2/
└─ setup.py

新结构:

/
├─ myproj/
│  ├─ common/ 
│  │  └─ mod1.py
│  ├─ subpackage1/
│  └─ subpackage2/
└─ setup.py

正如您所看到的那样,除了myproj现在是namespace package并且子包commonsubpackage1subpackage2现在可以改变之外没有太多变化独立分发。

是否仍然可以保留一个唯一的setup.py文件来创建3个独立的包?

  • myproj.common
  • myproj.subpackage1
  • myproj.subpackage2

另外,我想指定在安装myproj.subpackage1时,myproj.common是必需的,或myproj.subpackage2同时需要myproj.commonmyproj.subpackage1

1 个答案:

答案 0 :(得分:1)

正如Martijn Pieters所说,它只是python代码,所以是的,你可以做到这一点。我甚至认为这也不会那么困难。

基本上你只想操作setup.py

中的命令行参数
import sys

if sys.argv[1] == "subpackage1":
    # Remove the first command line argument so the setup function works normally.
    sys.argv.pop(1)

    # Run setup code for subpackage1 or 
    # Use a separate setup file and call "import setup_subpackage1"
    ...
elif sys.argv[1] == "subpackage2":
    # Remove the first command line argument so the setup function works normally.
    sys.argv.pop(1)

    # Run setup code for subpackage2 or
    # Use a separate setup file and call "import setup_subpackage2"
    ...
else:
    # Check if they gave common as an argument or just left if blank
    if sys.argv[1] == "common":
        # Remove the first command line argument so the setup function works normally.
        sys.argv.pop(1)

    # Run setup code for both packages.
    ...

虽然Martijn Pieters表示可能不值得努力。 Python的主要哲学是简单比复杂更好。如果你的两个子包完全不同,那么它们应该是不同的项目。

示例:Scipy

我试图想出一个为什么不这样做的例子,但显然scipy就是这样做的。所以我试图劝阻你可能是错的。仍然可能不值得努力,因为大多数人只是pip install scipy

很有意思。 Scipy的结构经过深思熟虑。 Scipy将每个子包都作为Python包(带有__init__.py文件的目录)。每个包里面都有一个setup.py文件。他们还使用numpy.distutils.misc_util.Configuration添加子包。

如果你查看他们的源代码,scipy的主要setup.py文件看起来像。

from __future__ import division, print_function, absolute_import

import sys


def configuration(parent_package='',top_path=None):
    from numpy.distutils.misc_util import Configuration
    config = Configuration('scipy',parent_package,top_path)
    config.add_subpackage('cluster')
    config.add_subpackage('constants')
    config.add_subpackage('fftpack')
    config.add_subpackage('integrate')
    config.add_subpackage('interpolate')
    config.add_subpackage('io')
    config.add_subpackage('linalg')
    config.add_data_files('*.pxd')
    config.add_subpackage('misc')
    config.add_subpackage('odr')
    config.add_subpackage('optimize')
    config.add_subpackage('signal')
    config.add_subpackage('sparse')
    config.add_subpackage('spatial')
    config.add_subpackage('special')
    config.add_subpackage('stats')
    config.add_subpackage('ndimage')
    config.add_subpackage('_build_utils')
    config.add_subpackage('_lib')
    config.make_config_py()
    return config

if __name__ == '__main__':
    from numpy.distutils.core import setup
    setup(**configuration(top_path='').todict())

所以看起来已经找到了一个很好的解决方案。