TL; DR:
Unter Python 3.3 müssen Sie nichts tun, nur keine __init__.py
in Ihre Namespace-Paketverzeichnisse einfügen, und es wird einfach funktionieren. Wählen Sie vor Version 3.3 die pkgutil.extend_path()
Lösung aus pkg_resources.declare_namespace()
, da sie zukunftssicher und bereits mit impliziten Namespace-Paketen kompatibel ist.
Python 3.3 führt implizite Namespace-Pakete ein, siehe PEP 420 .
Dies bedeutet, dass es jetzt drei Objekttypen gibt, die von einem erstellt werden können import foo
:
- Ein Modul, das durch eine
foo.py
Datei dargestellt wird
- Ein reguläres Paket, dargestellt durch ein Verzeichnis,
foo
das eine __init__.py
Datei enthält
- Ein Namespace-Paket, das durch ein oder mehrere Verzeichnisse
foo
ohne __init__.py
Dateien dargestellt wird
Pakete sind auch Module, aber hier meine ich "Nicht-Paket-Modul", wenn ich "Modul" sage.
Zuerst wird sys.path
nach einem Modul oder einem regulären Paket gesucht. Wenn dies erfolgreich ist, wird die Suche beendet und das Modul oder Paket erstellt und initialisiert. Wenn kein Modul oder reguläres Paket gefunden wurde, aber mindestens ein Verzeichnis gefunden wurde, wird ein Namespace-Paket erstellt und initialisiert.
Module und reguläre Pakete haben __file__
die .py
Datei festgelegt, aus der sie erstellt wurden. Reguläre Pakete und Namespace-Pakete haben __path__
das Verzeichnis oder die Verzeichnisse festgelegt, aus denen sie erstellt wurden.
Wenn Sie das tun import foo.bar
, geschieht das über den Such zuerst foo
, dann , wenn ein Paket gefunden wurde, für die Suche bar
mit getan wird foo.__path__
als Suchpfad statt sys.path
. If foo.bar
wird gefunden foo
und foo.bar
erstellt und initialisiert.
Wie mischen sich reguläre Pakete und Namespace-Pakete? Normalerweise nicht, aber die alte pkgutil
explizite Namespace-Paketmethode wurde um implizite Namespace-Pakete erweitert.
Wenn Sie ein reguläres Paket haben, das Folgendes hat __init__.py
:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
... das Legacy-Verhalten besteht darin, alle anderen regulären Pakete auf dem gesuchten Pfad zu seinem hinzuzufügen __path__
. In Python 3.3 werden jedoch auch Namespace-Pakete hinzugefügt.
Sie können also die folgende Verzeichnisstruktur haben:
├── path1
│ └── package
│ ├── __init__.py
│ └── foo.py
├── path2
│ └── package
│ └── bar.py
└── path3
└── package
├── __init__.py
└── baz.py
... und so lange , wie die beiden __init__.py
die haben extend_path
Linien (und path1
, path2
und path3
sind in Ihrem sys.path
) import package.foo
, import package.bar
und import package.baz
wird alle Arbeit.
pkg_resources.declare_namespace(__name__)
wurde nicht aktualisiert, um implizite Namespace-Pakete einzuschließen.