TL; DR:
auf Python 3.3 Sie setzen nicht alles tun, nur keine __init__.py
in Ihren Verzeichnissen Namespace-Paket und es wird funktionieren nur. Wählen Sie vor Version 3.3 die pkgutil.extend_path()
-Lösung über die pkg_resources.declare_namespace()
, da diese zukunftssicher und bereits mit impliziten Namespacepaketen kompatibel ist.
Python 3.3 führt implizite Namespace-Pakete, PEP 420 sehen.
Dies bedeutet, dass es nun drei Arten von Objekten sind, die von einer import foo
erstellt werden können:
- Ein Modul durch eine Datei
foo.py
dargestellt
- Ein regelmäßiges Paket von einem Verzeichnis dargestellt
foo
eine __init__.py
Datei enthält,
- Ein Namespace-Paket,
durch ein oder mehrere Verzeichnisse
foo
ohne
__init__.py
Dateien dargestellt
Pakete sind auch Module, aber hier meine ich "Nicht-Paket-Modul", wenn ich "Modul" sage.
Zuerst scannt sys.path
für ein Modul oder ein reguläres Paket. Wenn es erfolgreich ist, hört es auf zu suchen und erstellt und initialisiert das Modul oder Paket. Wenn kein Modul oder reguläres Paket gefunden wurde, aber mindestens ein Verzeichnis gefunden wurde, wird ein Namespacepaket erstellt und initialisiert.
Module und reguläre Pakete haben __file__
auf die .py
Datei festgelegt, aus der sie erstellt wurden. Reguläre und Namespacepakete haben __path__
auf das Verzeichnis oder die Verzeichnisse festgelegt, aus denen sie erstellt wurden.
Wenn Sie import foo.bar
tun, die oben Suche geschieht zuerst für foo
, dann, wenn ein Paket gefunden wurde, die Suche nach bar
mit foo.__path__
als Suchpfad getan statt sys.path
. Wenn foo.bar
gefunden wird, werden foo
und foo.bar
erstellt und initialisiert.
Wie also mischen sich reguläre Pakete und Namespacepakete? Normalerweise nicht, aber die alte pkgutil
explizite Namespace-Paketmethode wurde um implizite Namespacepakete erweitert.
Wenn Sie ein vorhandenes reguläres Paket, das ein __init__.py
so hat:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
... das Vermächtnis Verhalten andere regelmäßig Pakete auf dem gesuchten Weg zu seinem __path__
hinzuzufügen. Aber in Python 3.3 fügt es auch Namespacepakete hinzu.
So können Sie die folgende Verzeichnisstruktur haben:
├── path1
│ └── package
│ ├── __init__.py
│ └── foo.py
├── path2
│ └── package
│ └── bar.py
└── path3
└── package
├── __init__.py
└── baz.py
... und solange die beiden __init__.py
haben die extend_path
Linien (und path1
, path2
und path3
sind in Ihrem sys.path
) import package.foo
, import package.bar
und import package.baz
wird alles funktionieren.
pkg_resources.declare_namespace(__name__)
wurde nicht aktualisiert, um implizite Namespacepakete einzuschließen.
Es sieht für mich so aus, als wären Modul1 und Modul2 eigentlich Unterpakete statt Module. Wie ich es verstehe, ist ein Modul im Grunde eine einzige Datei. Vielleicht würden subpkg1 und subpkg2 mehr Sinn machen als Namen? – Alan