python名称空间与包:使包成为默认名称空间
我有一个项目,它有一个总体名称空间,里面有包。以下是文件夹结构:python名称空间与包:使包成为默认名称空间,python,module,namespace-package,Python,Module,Namespace Package,我有一个项目,它有一个总体名称空间,里面有包。以下是文件夹结构: pypackage ├── pypackage <-- Source code for use in this project. | | │ ├── bin <-- Module: Cli entry point into pyproject. | | ├── __init__.py | | └── pypackage.py | | |
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
它工作得很好,因为my 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',
]
},
...
)
import pypackage
然而,我有一个遗留代码,它导入了这个pypackage
,而以前它只是一个独立的python文件。像这样:
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',
]
},
...
)
import pypackage
那么,我如何使它保持名称空间和子包的相同结构,但仍然以旧的方式导入它呢?我该如何扭转这种局面:
from pypackage.core import pypackage
为此:
import pypackage
换句话说,当我将
pypackage
导入到外部项目中时,如何将pypackage.core.pypackage
模块别名为pypackage
?您可以通过导入顶级包在新包中添加“旧”名称
在pypackage/\uuuu init\uuuu.py
中作为全局变量导入的名称是pypackage
包上的属性。利用该功能访问“遗留”位置:
# add all public names from pypackage.core.pypackage to the top level for
# legacy package use
from .core.pypackage import *
现在,如果实际上这些对象是在pypackage.core.pypackage
中定义的,那么任何使用import pypackage
的代码都可以使用pypackage.foo
和pypackage.bar
现在,因为pypackage
是一个软件包,所以您有一个不同的问题;命名空间包用于安装多个单独的发行版,因此顶级包必须是空的,或者只包含一个最小的\uuuu init\uuuuu.py
文件(使用空目录创建的命名空间包需要Python 3.3)
如果您是使用此名称空间的发行版的唯一发布者,那么您可以在这里进行一些欺骗,并在您的核心包中使用一个文件,该文件可以与我上面使用的附加导入一起使用,但是,您不能在其他发行包中使用任何\uuuuu init\uuuuuuuuuy.py
文件,也不能要求它们都使用完全相同的\uuuuuuuuuuuuuu init.py
内容。协调是关键
或者你必须使用不同的方法。将pypackage
保留为旧包装器模块,并重命名新的包格式,以使用新的、不同的顶级名称,该名称可以位于旧模块旁边。此时,您可以直接将遗留包作为额外的顶级模块包含在项目中。您可以通过导入顶级包在新包中添加“旧”名称
在pypackage/\uuuu init\uuuu.py
中作为全局变量导入的名称是pypackage
包上的属性。利用该功能访问“遗留”位置:
# add all public names from pypackage.core.pypackage to the top level for
# legacy package use
from .core.pypackage import *
现在,如果实际上这些对象是在pypackage.core.pypackage
中定义的,那么任何使用import pypackage
的代码都可以使用pypackage.foo
和pypackage.bar
现在,因为pypackage
是一个软件包,所以您有一个不同的问题;命名空间包用于安装多个单独的发行版,因此顶级包必须是空的,或者只包含一个最小的\uuuu init\uuuuu.py
文件(使用空目录创建的命名空间包需要Python 3.3)
如果您是使用此名称空间的发行版的唯一发布者,那么您可以在这里进行一些欺骗,并在您的核心包中使用一个文件,该文件可以与我上面使用的附加导入一起使用,但是,您不能在其他发行包中使用任何\uuuuu init\uuuuuuuuuy.py
文件,也不能要求它们都使用完全相同的\uuuuuuuuuuuuuu init.py
内容。协调是关键
或者你必须使用不同的方法。将pypackage
保留为旧包装器模块,并重命名新的包格式,以使用新的、不同的顶级名称,该名称可以位于旧模块旁边。此时,您可以直接将遗留软件包作为额外的顶级模块包含在项目中。如果我使用软件包,Martin Pieters的想法是正确的,但名称空间软件包是一种设置工具
所以那没用。经过更多的研究,我明白了没有办法去做我想做的事情。因此,如果我真的想这样做,我必须将所有内容转换为常规的包层次结构,而不是名称空间包,然后使用martin的解决方案
我决定修改遗留代码,而不是以新的方式导入它。如果我使用的是包,Martin Pieters的想法是正确的,但是名称空间包是setuptools的东西
所以那没用。经过更多的研究,我明白了没有办法去做我想做的事情。因此,如果我真的想这样做,我必须将所有内容转换为常规的包层次结构,而不是名称空间包,然后使用martin的解决方案
我决定修改旧代码,而不是以新的方式导入它。对不起,我没有立即发现您制作了pypackage
名称空间包。我已经更新了我的答案,以反映其中的选项。@MartijnPieters谢谢,这有助于我更好地理解。对不起,我没有立即发现您制作了pypackage
名称空间包。我已经更新了我的答案,以反映其中的选项。@MartijnPieters谢谢,这有助于我更好地理解