TL; DR:
Pada Python 3.3 Anda tidak perlu melakukan apa-apa, hanya saja jangan memasukkan apa pun __init__.py
di 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.py
file
- Paket reguler, diwakili oleh direktori yang
foo
berisi __init__.py
file
- Paket namespace, diwakili oleh satu atau lebih direktori
foo
tanpa __init__.py
file
Paket adalah modul juga, tapi di sini maksud saya "modul non-paket" ketika saya mengatakan "modul".
Pertama memindai sys.path
modul 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 .py
file 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 bar
dilakukan dengan foo.__path__
sebagai jalur pencarian alih-alih sys.path
. Jika foo.bar
ditemukan, foo
dan foo.bar
dibuat serta diinisialisasi.
Jadi bagaimana paket reguler dan paket namespace tercampur? Biasanya tidak, tetapi pkgutil
metode paket namespace eksplisit lama telah diperluas untuk menyertakan paket namespace implisit.
Jika Anda memiliki paket reguler yang sudah ada yang memiliki __init__.py
seperti 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__.py
memiliki extend_path
garis (dan path1
, path2
dan path3
ada di Anda sys.path
) import package.foo
, import package.bar
dan import package.baz
semua akan bekerja.
pkg_resources.declare_namespace(__name__)
belum diperbarui untuk menyertakan paket namespace implisit.