python – 为什么setup.py在安装之前会扫描命名空间的内容?

我正在使用带有setuptools的命名空间在两个不同的存储库中分发相同的模块.目标是安装mymodule.one和mymodule.two,知道一个和两个的内容来自不同的回购.但看起来两个setup.py互相扫描内容.

├── repo1
│   ├── mymodule
│   │   ├── __init__.py
│   │   └── one
│   │       └── __init__.py
│   └── setup.py
└── repo2
    ├── mymodule
    │   ├── __init__.py
    │   └── two
    │       └── __init__.py
    └── setup.py

命名空间的下面是__init__.py:

test$cat repo1/mymodule/__init__.py 
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)

test$cat repo2/mymodule/__init__.py 
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)

setup.py声明了相同的名称:

test$cat repo1/setup.py 
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(name='mymodule', packages=find_packages())

test$cat repo2/setup.py 
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(name='mymodule', packages=find_packages())

从第一个包安装模块允许成功导入它:

test/repo1$ sudo python3 setup.py install
running install
Checking .pth file support in /usr/local/lib/python3.4/dist-packages/
/usr/bin/python3 -E -c pass
TEST PASSED: /usr/local/lib/python3.4/dist-packages/ appears to support .pth files
running bdist_egg
running egg_info
writing dependency_links to mymodule.egg-info/dependency_links.txt
writing mymodule.egg-info/PKG-INFO
writing top-level names to mymodule.egg-info/top_level.txt
reading manifest file 'mymodule.egg-info/SOURCES.txt'
writing manifest file 'mymodule.egg-info/SOURCES.txt'
installing library code to build/bdist.linux-x86_64/egg
running install_lib
running build_py
creating build/bdist.linux-x86_64/egg
creating build/bdist.linux-x86_64/egg/mymodule
copying build/lib/mymodule/__init__.py -> build/bdist.linux-x86_64/egg/mymodule
creating build/bdist.linux-x86_64/egg/mymodule/one
copying build/lib/mymodule/one/__init__.py -> build/bdist.linux-x86_64/egg/mymodule/one
byte-compiling build/bdist.linux-x86_64/egg/mymodule/__init__.py to __init__.cpython-34.pyc
byte-compiling build/bdist.linux-x86_64/egg/mymodule/one/__init__.py to __init__.cpython-34.pyc
creating build/bdist.linux-x86_64/egg/EGG-INFO
copying mymodule.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO
copying mymodule.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying mymodule.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying mymodule.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
zip_safe flag not set; analyzing archive contents...
mymodule.__pycache__.__init__.cpython-34: module references __path__
creating 'dist/mymodule-0.0.0-py3.4.egg' and adding 'build/bdist.linux-x86_64/egg' to it
removing 'build/bdist.linux-x86_64/egg' (and everything under it)
Processing mymodule-0.0.0-py3.4.egg
creating /usr/local/lib/python3.4/dist-packages/mymodule-0.0.0-py3.4.egg
Extracting mymodule-0.0.0-py3.4.egg to /usr/local/lib/python3.4/dist-packages
Adding mymodule 0.0.0 to easy-install.pth file

Installed /usr/local/lib/python3.4/dist-packages/mymodule-0.0.0-py3.4.egg
Processing dependencies for mymodule==0.0.0
Finished processing dependencies for mymodule==0.0.0

这是导入:

test/$ipython3
Python 3.4.3 (default, Oct 14 2015, 20:28:29) [...]

In [1]: from mymodule import [TAB]
extend_path  one    

现在我们从第二个存储库安装命名空间的另一部分:

test/repo2$sudo python3 setup.py install
running install
Checking .pth file support in /usr/local/lib/python3.4/dist-packages/
/usr/bin/python3 -E -c pass
TEST PASSED: /usr/local/lib/python3.4/dist-packages/ appears to support .pth files
running bdist_egg
running egg_info
creating mymodule.egg-info
writing mymodule.egg-info/PKG-INFO
writing top-level names to mymodule.egg-info/top_level.txt
writing dependency_links to mymodule.egg-info/dependency_links.txt
writing manifest file 'mymodule.egg-info/SOURCES.txt'
reading manifest file 'mymodule.egg-info/SOURCES.txt'
writing manifest file 'mymodule.egg-info/SOURCES.txt'
installing library code to build/bdist.linux-x86_64/egg
running install_lib
running build_py
creating build
creating build/lib
creating build/lib/mymodule
copying mymodule/__init__.py -> build/lib/mymodule
creating build/lib/mymodule/two
copying mymodule/two/__init__.py -> build/lib/mymodule/two
creating build/bdist.linux-x86_64
creating build/bdist.linux-x86_64/egg
creating build/bdist.linux-x86_64/egg/mymodule
copying build/lib/mymodule/__init__.py -> build/bdist.linux-x86_64/egg/mymodule
creating build/bdist.linux-x86_64/egg/mymodule/two
copying build/lib/mymodule/two/__init__.py -> build/bdist.linux-x86_64/egg/mymodule/two
byte-compiling build/bdist.linux-x86_64/egg/mymodule/__init__.py to __init__.cpython-34.pyc
byte-compiling build/bdist.linux-x86_64/egg/mymodule/two/__init__.py to __init__.cpython-34.pyc
creating build/bdist.linux-x86_64/egg/EGG-INFO
copying mymodule.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO
copying mymodule.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying mymodule.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying mymodule.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
zip_safe flag not set; analyzing archive contents...
mymodule.__pycache__.__init__.cpython-34: module references __path__
creating dist
creating 'dist/mymodule-0.0.0-py3.4.egg' and adding 'build/bdist.linux-x86_64/egg' to it
removing 'build/bdist.linux-x86_64/egg' (and everything under it)
Processing mymodule-0.0.0-py3.4.egg
removing '/usr/local/lib/python3.4/dist-packages/mymodule-0.0.0-py3.4.egg' (and everything under it)
creating /usr/local/lib/python3.4/dist-packages/mymodule-0.0.0-py3.4.egg
Extracting mymodule-0.0.0-py3.4.egg to /usr/local/lib/python3.4/dist-packages
mymodule 0.0.0 is already the active version in easy-install.pth

Installed /usr/local/lib/python3.4/dist-packages/mymodule-0.0.0-py3.4.egg
Processing dependencies for mymodule==0.0.0
Finished processing dependencies for mymodule==0.0.0

但试图再次导入一个失败,因为两个已经破坏它:

test/$ipython3
Python 3.4.3 (default, Oct 14 2015, 20:28:29) [...]

In [1]: from mymodule import [TAB]
extend_path  two   

In [1]: from mymodule import one
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-ddf1c613e57c> in <module>()
----> 1 from mymodule import one

ImportError: cannot import name 'one'

解决方法:

正确使用名称空间有两个要求.

> __init__.py模块声明了一个名称空间
> setup.py定义每个模块的唯一名称

__init__.py文件的内容应该是:

__import__('pkg_resources').declare_namespace(__name__)

然后是第一个模块的setup.py:

setup(name='mymodule_one', packages=find_packages('.'), 
      namespace_packages=['mymodule'])

和第二个模块

setup(name='mymodule_two', packages=find_packages('.'),
      namespace_packages=['mymodule'])

因此,应该能够安装和导入mymodule.one和mymodule.two

公共名称空间mymodule允许使用相同的名称导入两个模块.

每个模块的setup.py名称必须是唯一的,因为它用于模块的安装路径,并将覆盖共享它的任何内容,如您所见.

上一篇:python-使用setuptools包括Bash自动补全


下一篇:如何使用setuptools生成一个调用`python -m mypackage`的console_scripts入口点?