Python 使用setup.py时命名空间已损坏,并导致AttributeError:模块没有属性

Python 使用setup.py时命名空间已损坏,并导致AttributeError:模块没有属性,python,package,setuptools,Python,Package,Setuptools,我编写了一个重用现有名称空间的小工具(包),pki.server。我将我的包命名为pki.server.healthcheck。旧名称空间没有使用setuptools安装包,而我的包使用它 setup.py的内容 from setuptools import setup setup( name='pkihealthcheck', version='0.1', packages=[ 'pki.server.healthcheck.core',

我编写了一个重用现有名称空间的小工具(包),
pki.server
。我将我的包命名为
pki.server.healthcheck
。旧名称空间没有使用setuptools安装包,而我的包使用它

setup.py的内容

from setuptools import setup

setup(
    name='pkihealthcheck',
    version='0.1',
    packages=[
        'pki.server.healthcheck.core',
        'pki.server.healthcheck.meta',
    ],
    entry_points={
        # creates bin/pki-healthcheck
        'console_scripts': [
            'pki-healthcheck = pki.server.healthcheck.core.main:main'
        ]
    },
    classifiers=[
        'Programming Language :: Python :: 3.6',
    ],
    python_requires='!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*',
    setup_requires=['pytest-runner',],
    tests_require=['pytest',],
)
安装树(来自下面的场景1)如下所示:

# tree /usr/lib/python3.8/site-packages/pki/
├── __init__.py                     <---- Has methods and classes
├── cli
│   ├── __init__.py                 <---- Has methods and classes
│   ├── <some files>
├── server
│   ├── cli
│   │   ├── __init__.py             <---- Has methods and classes
│   │   ├── <Some files>
│   ├── deployment
│   │   ├── __init__.py             <---- Has methods and classes
│   │   ├── <some files>
│   │   └── scriptlets
│   │       ├── __init__.py         <---- Has methods and classes
│   │       ├── <some files>
│   ├── healthcheck
│   │   ├── core
│   │   │   ├── __init__.py         <---- EMPTY
│   │   │   └── main.py
│   │   └── pki
│   │       ├── __init__.py         <---- EMPTY
│   │       ├── certs.py
│   │       └── plugin.py
│   └── instance.py                 <---- Has class PKIInstance
└── <snip>

# tree /usr/lib/python3.8/site-packages/pkihealthcheck-0.1-py3.8.egg-info/
├── PKG-INFO
├── SOURCES.txt
├── dependency_links.txt
├── entry_points.txt
└── top_level.txt
场景2:pkgutil风格的命名空间包 我被限制使用此方法,因为我的另一个
\uuuu init\uuuu.py
包含类和函数

场景3:pkg_资源风格的命名空间包 虽然不推荐使用此方法,但我继续尝试,将
namespace=pki.server.healthcheck
添加到我的
setup.py
。这使得所有
pki.*
模块都不可见

因此,我确信场景1似乎最接近我想要实现的目标。我正在阅读一篇文章,以进一步了解python中导入的工作原理


我的问题是:为什么在我安装软件包后,一个完美工作的代码段会中断?

您的
\uuu init\uuuuuuuupy
文件需要导入这些文件。你有两个选择--

相对进口 pki/_init.py:
来自。导入服务器

pki/server/_init__uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.py:
来自。导入实例

绝对进口 pki/_init.py:
导入pki.server

pki/server/_init__uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.py:

导入pki.server.instance

我想这将解决我发布的特定场景。但是,可能有多个模块需要更正。因此,我想了解屏幕后面发生了什么。对于一个包,
import xyz.abc
导入的是
import xyz.abc/\uuuu init\uuuuuuuuuuy.py
文件内容。因此,您想要公开的任何内容都需要在init文件中。一些包限制从顶层导出的内容--
scipy.sparse
必须作为
从scipy导入sparse
导入scipy.sparse
导入,方法是不在init文件中包含
sparse
,以防止自动加载大量代码。
# This used to work before my package gets installed
>>> import pki.server
>>> instance = pki.server.instance.PKIInstance("pki-tomcat")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'pki.server' has no attribute 'instance'
>>> import pki.server.instance
>>> instance = pki.server.instance.PKIInstance("pki-tomcat")
>>> instance
pki-tomcat