python命名空间与软件包:将软件包设为默认命名空间

时间:2018-11-26 17:48:19

标签: python module namespace-package

我有一个带有总体命名空间的项目,其中包含程序包。这是文件夹结构:

pypackage
├── pypackage             <-- Source code for use in this project.
|   |
│   ├── bin               <-- Module: Cli entry point into pyproject.
|   |   ├── __init__.py
|   |   └── pypackage.py
|   |
|   └── core              <-- Module: Core functionality.
|       ├── __init__.py
|       └── pypackage.py
|
├── tests             
├── README.md         
└── setup.py          

非常简单。如果要导入,请使用:

from pypackage.core import pypackage

,它的效果很好,因为我的setup.py看起来像这样:

from setuptools import setup, find_packages
...
NAME = 'pypackage'
setup(
    name=NAME,
    namespace_packages=[NAME],
    packages=[f'{NAME}.{p}' for p in find_packages(where=NAME)],
    entry_points={
        "console_scripts": [
            f'{NAME} = {NAME}.bin.{NAME}:cli',
        ]
    },
    ...
)

但是,我有旧版代码,当它以前只是一个独立的python文件时,会导入此pypackage。像这样:

import pypackage

那么我该如何做,以便可以与名称空间和子包保持相同的结构,但仍以旧方式导入它?我该如何转动:

from pypackage.core import pypackage

对此:

import pypackage

换句话说,在将pypackage.core.pypackage导入到外部项目中时,如何将pypackage模块的别名为pypackage >

2 个答案:

答案 0 :(得分:2)

您可以通过导入到顶级程序包中,在新程序包中添加“旧”名称。

pypackage/__init__.py包中的属性是在pypackage中作为全局变量导入的名称。利用它可以访问“旧版”位置:

# add all public names from pypackage.core.pypackage to the top level for
# legacy package use
from .core.pypackage import *

现在,如果实际上使用import pypackage定义了这些对象,那么任何使用pypackage.foo的代码都可以使用pypackage.barpypackage.core.pypackage

现在,由于pypackagesetuptools namespace package,所以您遇到了另一个问题。命名空间包可用于安装多个单独的发行版,因此顶级包必须为 empty 或仅包含最小的__init__.py文件(使用空目录创建的命名空间包需要Python 3.3)

如果您是使用此名称空间的发行版的唯一发行商,则可以在此处作弊,并在您的__init__.py包中使用一个单个 core文件pkg-util-style __init__.py file和上面我使用的其他导入一样,但是您不得在其他分发程序包中使用任何__init__.py文件,或要求它们都使用完全相同的{{1} }内容。协调是这里的关键。

否则,您将不得不使用其他方法。将__init__.py保留为旧包装模块,然后重命名新的包格式,以使用可以在旧模块旁边使用的新的顶层名称。此时,您可以直接将遗留包作为额外的顶级模块包含在项目中。

答案 1 :(得分:0)

如果我使用软件包,Martin Pieters的想法是正确的,但是名称空间软件包是setuptools的事情。

所以没有用。经过更多的研究,我了解到没有办法去做我想做的事情。因此,如果我真的想这样做,则必须将所有内容都转换为常规的包层次结构,而不是名称空间包,然后使用马丁的解决方案。

我已决定修改旧代码,而不是以新方式导入它。