2016-08-12 53 views
1

我使用setuptools命名空间在两个不同的存储库中分发相同的模块。目标是安装mymodule.onemymodule.two,因为知道onetwo的内容来自不同的回购站。但它看起来像两个setup.py对方内容。为什么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' 

回答

2

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

  1. 模块__init__.py声明一个名称空间
  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

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

给每个模块的setup.py的name需要是唯一的,因为它用于模块的安装路径,并且会覆盖共享它的任何东西,正如您所看到的。

+0

它的工作原理!为什么人们也提出'extend_path(__ path__,__name __)'选项?使用'extend_path' +'namespace_packages',安装程序会抱怨,因为'__init__.py不会调用declare_namespace()'。但[此评论](http:// stackoverflow。com/questions/1675734/how-do-i-create-a-namespace-package-in-python#comment1550515_1676069)建议不建议使用'__import__'。 – myoan

+1

命名空间有多种实现。 'extend_path'是'pkgutil',现在是python3的stdlib的一部分。 'pkg_resources'由setuptools提供,并且与py2和py3兼容。 setup.py中的'namespace_packages'专门用于'pkg_resources',不能与'pkgutil'一起使用。导入注释是有效的,但如果更改为常规导入,它将打破.egg文件。答案使用'pkg_resources',因为它可以在setuptools上工作,而'extend_path'不会像py2上的那样工作。 – danny

相关问题