Namespace corrupted when using setup.py and causes AttributeError: module has no attribute
Namespace corrupted when using setup.py and causes AttributeError: module has no attribute
我写了一个重用现有命名空间的小工具(包),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-style 命名空间包
虽然不推荐这种方法,但我继续尝试将 namespace=pki.server.healthcheck
添加到我的 setup.py
中。这使得所有 pki.*
个模块不可见
所以我确信场景 1 似乎最接近我想要实现的目标。我正在阅读 old post 以了解有关 python 中的导入如何工作的更多信息。
我的问题是:为什么在我安装包后完美运行的片段会中断?
您的 __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
我写了一个重用现有命名空间的小工具(包),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-style 命名空间包
虽然不推荐这种方法,但我继续尝试将 namespace=pki.server.healthcheck
添加到我的 setup.py
中。这使得所有 pki.*
个模块不可见
所以我确信场景 1 似乎最接近我想要实现的目标。我正在阅读 old post 以了解有关 python 中的导入如何工作的更多信息。
我的问题是:为什么在我安装包后完美运行的片段会中断?
您的 __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