为什么setup.py在安装前扫了命名空间的内容?

Why does setup.py sweeps the content of the namespace before installing?

我将命名空间与设置工具一起使用,以在两个不同的存储库中分发相同的模块。目标是安装 mymodule.onemymodule.two,知道 onetwo 的内容来自不同的回购协议。不过好像是两个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

但再次尝试导入 one 失败,因为 two 已将其丢弃:

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'

正确使用名称 spaces 有两个要求。

  1. __init__.py 个模块声明了名称 space
  2. 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.onemymodule.two

公共名称space mymodule 允许使用相同的名称导入两个模块。

为每个模块提供给 setup.py 的 name 需要是唯一的,因为它用于模块的安装路径,并将覆盖共享它的任何内容,如您所见。