2016-08-12 4 views
1

Ich benutze Namespaces mit setuptools, um ein und dasselbe Modul in zwei verschiedenen Repositories zu verteilen. Das Ziel ist, mymodule.one und mymodule.two installiert zu bekommen, wissend, dass der Inhalt von one und two von verschiedenen Repos kommt. Aber es sieht aus wie zwei setup.py gegenseitig Inhalt zu fegen.Warum scilet setup.py den Inhalt des Namespace vor der Installation?

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

Der Namespace hat das __init__.py unter:

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__) 

Der setup.py erklärt den gleichen Namen:

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()) 

Installation des Moduls aus dem ersten Paket ermöglicht es erfolgreich zu importieren:

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 

Hier ist der Import:

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

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

Jetzt installieren wir den anderen Teil des Namespace aus dem zweiten Repository:

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 

Doch der Versuch, one wieder zu importieren versagt seit two hat es im Papierkorb:

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' 

Antwort

2

Es gibt zwei Voraussetzungen für die korrekte Verwendung von Namensräumen.

  1. __init__.py der Module deklarieren einen Namensraum
  2. setup.py definiert einzigartige Namen für jedes Modul

Der Inhalt beider __init__.py Dateien sein sollte:

__import__('pkg_resources').declare_namespace(__name__) 

Dann setup.py für das erste Modul:

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

und zweite Modul

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

Als Ergebnis sollte in der Lage sein, sowohl Raum mymodule.one und mymodule.two

Der gemeinsame Name importiert beide Module mymodule erlaubt werden installieren und importieren mit dem gleichen Namen.

Die name, die für setup.py für jedes Modul angegeben wird, muss eindeutig sein, da es für den Installationspfad des Moduls verwendet wird und alles überschreibt, das es teilt, wie Sie gesehen haben.

+0

Es funktioniert! Warum schlagen Leute auch die Option 'extend_path (__ path__, __name __)' vor? Mit 'extend_path' +' namespace_packages' beschwert sich das Installationsprogramm, weil '__init__.py declare_namespace()' nicht aufruft. Aber [dieser Kommentar] (http: // stackoverflow.com/questions/1675734/how-do-ich-create-a-namespace-package-in-python # comment1550515_1676069) schlägt vor, dass "__import__" nicht empfohlen wird. – myoan

+1

Es gibt mehrere Implementierungen von Namespaces. 'extend_path' ist für' pkgutil', jetzt Teil von stdlib ab python3. 'pkg_resources' wird von setuptools zur Verfügung gestellt und ist sowohl mit py2 als auch mit py3 kompatibel. 'namespace_packages' in setup.py ist spezifisch für' pkg_resources' und kann nicht mit 'pkgutil' verwendet werden. Der Importkommentar ist zwar gültig, bricht jedoch .egg-Dateien ab, wenn er in einen regulären Import geändert wird. Die Antwort verwendet 'pkg_resources', da dies mit setuptools funktioniert, während' extend_path' nicht wie auf py2 funktioniert. – danny

Verwandte Themen