2016-08-12 6 views
1

Я использую пространства имен с setuptools для распространения одного и того же модуля в двух разных хранилищах. Цель состоит в том, чтобы установить mymodule.one и mymodule.two, зная, что содержимое one и two происходит из разных репозиториев. Но похоже, что два 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.one и mymodule.two

Общее пространство имен mymodule позволяет оба модуля должны быть импортированы с тем же именем.

name, указанный в файле setup.py для каждого модуля, должен быть уникальным, так как он используется для пути установки модуля и перезаписывает все, что разделяет его, как вы видели.

+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', теперь является частью stdlib от python3. 'pkg_resources' предоставляется setuptools и совместим как с py2, так и с py3. 'namespace_packages' в файле setup.py для' pkg_resources' специально, не может использовать его с 'pkgutil'. Комментарий импорта действителен, хотя он будет разорвать файлы .egg, если их изменить на обычный импорт. Ответ использует 'pkg_resources', поскольку это будет работать на что-либо с setuptools, в то время как' extend_path' не будет работать так же, как на py2. – danny

Смежные вопросы