TL; DR:
Pada Python 3.3 Anda tidak perlu melakukan apa-apa, hanya saja jangan memasukkan apa pun __init__.pydi direktori paket namespace Anda dan itu hanya akan berfungsi. Pada pra-3.3, pilih pkgutil.extend_path()solusinya pkg_resources.declare_namespace(), karena ini adalah bukti masa depan dan sudah kompatibel dengan paket namespace implisit.
Python 3.3 memperkenalkan paket namespace implisit, lihat PEP 420 .
Ini berarti sekarang ada tiga jenis objek yang dapat dibuat oleh import foo:
- Modul diwakili oleh
foo.pyfile
- Paket reguler, diwakili oleh direktori yang
fooberisi __init__.pyfile
- Paket namespace, diwakili oleh satu atau lebih direktori
footanpa __init__.pyfile
Paket adalah modul juga, tapi di sini maksud saya "modul non-paket" ketika saya mengatakan "modul".
Pertama memindai sys.pathmodul atau paket reguler. Jika berhasil, ia berhenti mencari dan membuat dan menginisialisasi modul atau paket. Jika tidak menemukan modul atau paket reguler, tetapi ia menemukan setidaknya satu direktori, itu membuat dan menginisialisasi paket namespace.
Modul dan paket reguler telah __file__diatur ke .pyfile tempat mereka dibuat. Paket reguler dan namespace telah __path__ditetapkan ke direktori atau direktori tempat mereka dibuat.
Ketika Anda melakukannya import foo.bar, pencarian di atas terjadi terlebih dahulu foo, kemudian jika sebuah paket ditemukan, pencarian bardilakukan dengan foo.__path__sebagai jalur pencarian alih-alih sys.path. Jika foo.barditemukan, foodan foo.bardibuat serta diinisialisasi.
Jadi bagaimana paket reguler dan paket namespace tercampur? Biasanya tidak, tetapi pkgutilmetode paket namespace eksplisit lama telah diperluas untuk menyertakan paket namespace implisit.
Jika Anda memiliki paket reguler yang sudah ada yang memiliki __init__.pyseperti ini:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
... perilaku lawas adalah menambahkan paket reguler lain di jalur yang dicari ke __path__. Namun dalam Python 3.3, ia juga menambahkan paket namespace.
Jadi Anda dapat memiliki struktur direktori berikut:
├── path1
│ └── package
│ ├── __init__.py
│ └── foo.py
├── path2
│ └── package
│ └── bar.py
└── path3
└── package
├── __init__.py
└── baz.py
... dan selama keduanya __init__.pymemiliki extend_pathgaris (dan path1, path2dan path3ada di Anda sys.path) import package.foo, import package.bardan import package.bazsemua akan bekerja.
pkg_resources.declare_namespace(__name__) belum diperbarui untuk menyertakan paket namespace implisit.