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

时间:2019-12-20 22:31:34

标签: 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.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

我阅读了official documentation,并尝试了所有3种建议的方法。我看到了以下结果:

方案1:本机名称空间包

起初,一切似乎都很顺利。但是:

# 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

方案2:pkgutil样式的名称空间包 由于其他__init__.py包含类和函数,我无法使用此方法

方案3:pkg_resources样式的名称空间包 尽管不建议使用此方法,但我继续进行尝试,将namespace=pki.server.healthcheck添加到了setup.py中。这使得所有pki.*模块都不可见

因此,我确信方案1似乎是我想要达到的最接近的方案。我正在阅读old post,以了解有关python导入如何工作的更多信息。

我的问题是:为什么安装软件包后无法正常工作的代码段会中断?

1 个答案:

答案 0 :(得分:1)

您的__init__.py文件需要导入文件。您有两个选择-absolute and relative imports

相对进口

pki / __ init__.py:
from . import server

pki / server / __ init__.py:
from . import instance

绝对进口

pki / __ init__.py:
import pki.server

pki / server / __ init__.py:
import pki.server.instance