我有一个带有总体命名空间的项目,其中包含程序包。这是文件夹结构:
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
? >
答案 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.bar
和pypackage.core.pypackage
。
现在,由于pypackage
是setuptools 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的事情。
所以没有用。经过更多的研究,我了解到没有办法去做我想做的事情。因此,如果我真的想这样做,则必须将所有内容都转换为常规的包层次结构,而不是名称空间包,然后使用马丁的解决方案。
我已决定修改旧代码,而不是以新方式导入它。