python名称空间与包:使包成为默认名称p

2024-05-23 15:04:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个具有全局命名空间的项目,其中包含包。以下是文件夹结构:

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          

很简单。如果我想导入它,我使用:

^{pr2}$

因为我的设置.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

那么,如何使它保持与名称空间和子包相同的结构,但仍然以旧的方式导入它呢?我该怎么转这个:

^{pr2}$

在这方面:

import pypackage

换句话说,当我将pypackage导入外部项目时,如何将pypackage.core.pypackage模块命名为pypackage


Tags: 项目nameinpyimportforbinpackages
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.core.pypackage中定义的。在

现在,由于pypackage是一个setuptools namespace package,您有一个不同的问题;名称空间包有多个单独的发行版来安装,因此顶级包必须是空的或只包含一个最小的__init__.py文件(使用空目录创建的命名空间包需要python3.3)。在

如果您是使用此命名空间的发行版的唯一发行者,那么您可以在这里稍微作弊,并在您的core包中使用一个单个__init__.py文件,该文件可以使用pkg-util-style ^{} file与我上面使用的附加导入一起使用,但是,您不能在其他发行包中使用任何__init__.py文件,或者要求它们都使用完全相同的__init__.py内容。协调是关键。在

否则你就得用另一种方法了。将pypackage保留为旧的包装器模块,并重命名新的包格式,以使用可以位于旧模块旁边的新的不同顶层名称。此时,您可以将遗留包直接作为额外的顶层模块包含在项目中。在

如果我使用包,martinpieters的想法是正确的,但是名称空间包是setuptools的东西。在

所以那没用。经过更多的研究,我明白了做我想做的事是不可能的。所以如果我真的想这么做,我必须把所有的东西都转换成一个常规的包层次结构,而不是命名空间包,然后使用martin的解决方案。在

我决定修改遗留代码,以新的方式导入它。在

相关问题 更多 >