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'
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
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