TL; DR:
Python 3.3'te hiçbir şey yapmanız gerekmiyor, sadece __init__.py
ad alanı paket dizinlerinize herhangi bir şey koymayın ve sadece işe yarayacak. 3.3 öncesi sürümde, pkgutil.extend_path()
çözümü pkg_resources.declare_namespace()
geleceğe göre seçin ve örtük ad alanı paketleriyle zaten uyumludur.
Python 3.3 kapalı ad alanı paketleri sunar, bkz. PEP 420 .
Bu, şu anda bir tarafından oluşturulabilecek üç tür nesne olduğu anlamına gelir import foo
:
- Bir
foo.py
dosya ile temsil edilen modül
- Dosya
foo
içeren bir dizinle temsil edilen normal bir paket__init__.py
- Bir veya daha fazla dizinleri ile temsil edilen bir ad paketi
foo
herhangi olmadan __init__.py
dosyaları
Paketler de modüller, ama burada "modül" dediğimde "paket dışı modül" demek istiyorum.
İlk sys.path
olarak bir modül veya normal paket tarar . Başarılı olursa aramayı durdurur ve modülü veya paketi oluşturur ve başlatır. Herhangi bir modül veya normal paket bulamadıysa, ancak en az bir dizin bulduysa, bir ad alanı paketi oluşturur ve başlatır.
Modüller ve normal paketler , oluşturuldukları dosyaya __file__
ayarlanmıştır .py
. Normal ve ad alanı paketleri __path__
, oluşturuldukları dizine veya dizinlere ayarlanmıştır.
Bunu yaptığınızda import foo.bar
, yukarıdaki arama önce gerçekleşir foo
, ardından bir paket bulunursa, arama yerine arama yolu olarak bar
yapılır . Eğer bulunursa ve oluşturulur ve başlatılırsa.foo.__path__
sys.path
foo.bar
foo
foo.bar
Peki, normal paketler ve ad alanı paketleri nasıl karışır? Normalde yoktur, ancak eski pkgutil
açık ad alanı paketi yöntemi örtük ad alanı paketlerini içerecek şekilde genişletilmiştir.
Şuna benzer mevcut bir normal paketiniz varsa __init__.py
:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
... eski davranış, aranan yola başka düzenli paketleri eklemektir .__path__
. Ancak Python 3.3'te ad alanı paketleri de ekler.
Böylece aşağıdaki dizin yapısına sahip olabilirsiniz:
├── path1
│ └── package
│ ├── __init__.py
│ └── foo.py
├── path2
│ └── package
│ └── bar.py
└── path3
└── package
├── __init__.py
└── baz.py
... ve sürece iki yanı __init__.py
var extend_path
hatları (ve path1
, path2
ve path3
Gözlerinde farklı olan sys.path
) import package.foo
, import package.bar
ve import package.baz
tüm çalışma olacak.
pkg_resources.declare_namespace(__name__)
örtük ad alanı paketleri içerecek şekilde güncellenmedi.