Paketler "noktalı modül isimleri" kullanarak Python'un modül isim
alanının düzenlenmesinde kullanılırlar. Örneğin modül adı
A.B adı A olan bir paket
içindeki B adlı alt modülü gösterir. Nasıl modüller
farklı modül yazarlarını birbirlerinin kullandığı global değişkenleri
dert etmekten kurtarıyorsa, paketler de NumPy ya da
PyOpenGL gibi çok sayıda modül içeren paketlerin
birbirlerinin modül isimlerinin çakışması tehlikesinden kurtarır.
Ses dosyaları ve ses verisi üzerinde işlem yapacak bir modül kolleksiyonu
(bir "paket") geliştirmek istediğinizi düşünelim. Farklı biçemlerdeki ses
dosyalarını (.wav, .aiff,
.au gibi dosya uzantıları olan) birbirine dönüştürmek,
seslere efektler uygulamak veya sesleri filtrelemek için pek çok modüle
ihtiyacınız olacak. Paketinizin muhtemel dizin yapısı şöyle olabilir:
Sound/ Paketin en üst seviyesi
__init__.py paketi ilk kullanıma hazırlama
Formats/ Farklı dosya biçemleri için alt paket
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
Effects/ ses efektleri alt paketi
__init__.py
echo.py
surround.py
reverse.py
...
Filters/ filtre alt paketi
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
__init__.py dosyaları Python'un bu dizinleri paket
içeren dizinler olarak algılaması için gereklidirler. Bunlar aynı isimli
dizinlerin modül arama yolunda bulunacak diğer geçerli modülleri istemdışı
saklamasını engeller. __init__.py boş bir dosya
olabileceği gibi paketi ilk çalışmaya hazırlayabilir ya da daha sonra
açıklanacak olan __all__ değişkenine değer atıyor olabilir.
Paketin kullanıcısı paketten dilediği bir modülü yükleyebilir.
import Sound.Effects.echo
Bu Sound.Effects.echo modülünü yükler. Modüle tüm
ismi ile atıfta bulunulmalı:
Sound.Effects.echo.echofilter(input, output, delay=0.7, atten=4)
Aynı modülü yüklemenin bir diğer yolu:
from Sound.Effects import echo
Bu da echo alt modülünü yükler; ancak bunu paket adı
verilmeden erişilebilir kılar ve modül şu şekilde kullanılabilir:
echo.echofilter(input, output, delay=0.7, atten=4)
Bir diğer yol da istenen işlev ya da değişkeni doğrudan yüklemektir:
from Sound.Effects.echo import echofilter
Bu da echo modülünü yükler; ancak
echofilter() işlevini doğrudan erişilebilir kılar:
echofilter(input, output, delay=0.7, atten=4)
from PAKET import İSİM kullanılırken İSİM bir alt
modül, alt paket ya da paket içinde tanımlı bir işlev, sınıf veya
değişken ifade eden herhangi bir isim olabilir. import
deyimi önce ismin pakette tanımlı olup olmadığına bakar; tanımlı değil
ise bunun bir modül olduğunu varsayar ve bunu yüklemeye teşebbüs eder.
Modülü bulamaz ise ImportError istisnası oluşur.
import ÖĞE.ALTÖĞE.ALTALTÖĞE ifadesinde ise son
ismin dışındaki isimler paket olmalıdır. Son isim bir modül veya paket
olabilir; ancak bir önceki ismin içinde tanımlanan bir işlev ya da
değişken olamaz.
Kullanıcı from Sound.Effects import * yazdığında ne olur?
Dosya sistemine ulaşılıp paketin içinde hangi alt paketlerin olduğunun
bulunması ve hepsinin yüklenmesi beklenir. Ne yazık ki bu işlem küçük/büyük
harf ayrımının olmadığı Windows ve Mac işletim sistemlerinde pek iyi çalışmaz.
Bu işletim sistemlerinde ECHO.PY gibi bir dosyanın
echo, Echo veya ECHO
isimlerinden hangisi ile yüklenmesi gerektiğini belirlemenin garantili bir
yolu yoktur. Örneğin, Windows 95 dosya adlarının ilk harfini daima büyük harf
ile gösterir. DOS'un 8+3 harflik dosya adı uzunluğu kısıtlaması da uzun modül
isimleri için sorun olmaktadır.
Tek çözüm paket yazarının açık bir paket indeksi hazırlamasıdır. Bir
paketin __init__.py dosyası __all__
adlı bir liste tanımlıyorsa bu liste from PAKET import *
ifadesi kullanıldığında yüklenecek modül isimlerinin listesi olarak kullanılır.
Paketin yeni bir sürümü hazırlandığında bu listenin uygun şekilde
güncellenmesi paket yazarının sorumluğundadır. Eğer paketten *
yüklemeye ihtiyaç duyulmayacağına karar verilirse bu özellik kullanılmayabilir.
Örneğin Sounds/Effects/__init__.py dosyasının içeriği
şöyle olabilir:
__all__ = ["echo", "surround", "reverse"]
Bu from Sound.Effects import * ifadesinin Sound
paketinden isimleri __all__ içinde geçen üç modülün
yüklemesini sağlar.
__all__ tanımlanmamış ise
from Sound.Effects import * ifadesi Sound.Effects
paketindeki bütün alt modülleri yürürlükte olan isim alanına yüklemez;
sadece Sound.Effects paketinin ve içindeki isimlerin
yüklenmesini sağlar (muhtemelen __init__.py) dosyasını
çalıştırdıktan sonra). Bundan önceki import deyimlerince
yüklenen alt paketler de yüklenir. Şu koda bir bakalım:
import Sound.Effects.echo
import Sound.Effects.surround
from Sound.Effects import *
Bu örnekte echo ve surround
modülleri from...import... ifadesi çalıştırıldığında
Sound.Effects paketinde tanımlı oldukları için
yürürlükte olan isim alanına yüklenirler. Bu __all__
tanımlı olduğunda da bu çalışır.
Genel olarak bir modül ya da paketten * yüklemek
hoş karşılanmaz; çünkü çoğunlukla zor okunan koda neden olur. Bunun
etkileşimli kipte kullanılmasının bir sakıncası yoktur. Ayrıca bazı
modüller sadece belirli bir kalıba uyan isimleri verecek şekilde
tasarlanmışlardır.
from PAKET import GEREKLİ_ALTMODÜL ifadesini
kullanmanın hiç bir kötü tarafı yoktur. Yükleyen modül farklı
paketlerden aynı isimli modüller yüklemeye gereksinim duymadığı
sürece tavsiye edilen kullanım şekli de budur.
Birbirlerini Yükleyen Modüller
Alt modüller çoğu kez birbirlerine atıfta bulunurlar. Örneğin
surround modülü echo modülüne ihtiyaç duyabilir. Aslında bu
türden atıflar öyle yaygındır ki import
deyimi standart modül arama yoluna bakmadan önce çağrıldığı
paketin içinde arama yapar. Bu şekilde surround modülü
import echo veya
from echo import echofilter ifadeleri ile
kolayca echo modülüne kavuşabilir. Yüklenmek istenen modül içinde
bulunan pakette (yükleme yapmaya çalışan modülün bulunduğu paket)
bulunamaz ise import deyimi aynı isimli üst
seviyeli bir modül arar.
Paketler Sound paketindeki gibi alt paketler şeklinde düzenlenmişler
ise farklı alt paketler içindeki modüllerin birbirilerine atıfta
bulunmasının kısa bir yolu yoktur; paketin tam adı kullanılmalıdır.
Örneğin, Sound.Filters.vocoder modülünün echo modülünü kullanması
gerekiyor ise from Sound.Effects import echo
ifadesi ile buna erişebilir.