TL; DR:
Python 3.3'te hiçbir şey yapmanız gerekmiyor, sadece __init__.pyad 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.pydosya ile temsil edilen modül
- Dosya
fooiçeren bir dizinle temsil edilen normal bir paket__init__.py
- Bir veya daha fazla dizinleri ile temsil edilen bir ad paketi
fooherhangi olmadan __init__.pydosyaları
Paketler de modüller, ama burada "modül" dediğimde "paket dışı modül" demek istiyorum.
İlk sys.patholarak 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 baryapılır . Eğer bulunursa ve oluşturulur ve başlatılırsa.foo.__path__sys.pathfoo.barfoofoo.bar
Peki, normal paketler ve ad alanı paketleri nasıl karışır? Normalde yoktur, ancak eski pkgutilaçı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__.pyvar extend_pathhatları (ve path1, path2ve path3Gözlerinde farklı olan sys.path) import package.foo, import package.barve import package.baztüm çalışma olacak.
pkg_resources.declare_namespace(__name__) örtük ad alanı paketleri içerecek şekilde güncellenmedi.