2016-08-12 24 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

相關問題