Python Modül Yapısı
Python dilinde ilerlemeden önce modül yapısının anlaşılmasının daha yararlı olduğunu düşünüyorum. Dili öğrenmeye girişte genellikle tek bir dosya içerisinde birtakım sınıflar, metodlar ve fonksiyonlar tanımlanarak örneklendirilir ancak bizim buradaki hedefimiz öncelikli olarak bunların nasıl çalıştığı ve nasıl bir araya geldiğini görmek. Bunu kavradıktan sonra Python örneklerini ve dili anlamaya çalışacağız çünkü tek bir dosya örneği birden fazla dosyaya çok çabuk şekilde evriliyor.
Burada fikir sahibi olacağımız konu Python'un kendi içerisinde bir kodu nasıl çalıştırdığı ve
import
anahtar kelimesi ile yazdığımız satırları nasıl yorumladığı. Hatırlarsanız faktöriyel ve
web sayfası örneklerinde math ve requests
modüllerini kullanmıştık ancak nasıl çalıştıklarına
terminal komutu nasıl çalışır makalesindeki gibi değinmemiştik. Bu
bölümde buna değineceğiz.
Modüller Nasıl Yüklenir¶
Öncelikle Python'ın bu modülün nerede olduğunu bulması gerekiyor. Bunu yaparken de kullandığımız
shell nasıl ortam değişkenlerini kullanıp bir uygulamayı buluyorsa, Python da kendi içerisinde
modülleri aradığı dizinlere bakıyor. Bu dizinlerin neler olduğunu sys
modülünü yükleyerek
görebiliyoruz.
Sanal ortamınızı aktive ettikten sonra ipython
komutunu çalıştırın
ve aşağıdaki kod parçacığını girin:
IPython Kodu Kopyalama
Burada direkt olarak In [1]:
satırları ile kodu kopyalayıp IPython içerisine
yapıştırabilirsiniz. IPython otomatik olarak bu satırları almayacak ve kodu çalıştıracaktır.
IPython hangi komutun çıktısının ne olduğunu Out [2]
satırı ile göstermekte ve bize yardımcı
olmakta.
Sonuç olarak aşağıdakine benzer bir çıktı göreceksiniz.
Out[2]:
['/home/eren.linux/src/sonradanogrendiklerim/venv/bin',
'/usr/lib/python310.zip',
'/usr/lib/python3.10', # ---> Python'un kendi içerisinde gelen modülleri
'/usr/lib/python3.10/lib-dynload',
'', # ---> içinde bulunduğumuz dizin
'/home/eren.linux/src/sonradanogrendiklerim/venv/lib/python3.10/site-packages']
# |
# |----> dışarıdan yüklediğimiz paketlerin bulunduğu sanal ortam dizini
Burada gördüğümüz çıktıdan anladığımız üzere Python herhangi bir import
anahtar kelimesi
gördüğünde bu dizinlere sırası ile, teker teker bakıyor ve modülü yüklemeye çalışıyor.
Kendi Modülümüzü Oluşturalım¶
Bunun için tek yapmamız gereken proje dizininde py
uzantılı bir dosya oluşturmak.
ilkadim.py içerisindeki toplama işlemi bu noktada güzel bir tercih
olabillir. Tek bir dosya yerine toplama işlemini ayırıp, ayrı bir modülden çağıracağız.
Öncelikle matematik.py
isimli bir dosya oluşturun ve toplama işlemini buraya taşıyın:
Sonrasında ilkadim.py
içerisindeki aynı kodu silin ve import
ile bu modülü yükleyin:
Tebrikler. İlk modülümüzü oluşturduk. Python modül ararken matematik.py
dosyasını diğer dizinlerde
bulamadı, şu an bulunduğumuz dizine sıra geldi, buldu ve yükledi.
Burada sadece dosya isiminden giderek modülü yükledik ancak birden fazla dosyaya sahip olan modüller de karşımıza çıkacak, requests modülünde olduğu gibi. Bu modüller bir dizin içerisinde yer alıyor ve birden fazla dosyaya sahip olabiliyor. Şimdi dizin içerisindeki modüllerin nasıl yüklendiğine bakalım.
Modül Dizini ve __init__.py
¶
requests
modülüne bakacak olursak site-packages
dizinine göz atmamız yeterli.
❯ pwd
/home/eren.linux/src/sonradanogrendiklerim
❯ ls venv/lib/python3.10/site-packages/requests/
__init__.py __version__.py adapters.py auth.py ...
Gördüğümüz gibi requests
modülü bir dizin olarak yer alıyor ve import requests
satırı
çalıştırıldığında bu dizinden okunup modül yükleniyor. Modülün çeşitli dosyalara ayrıldığını
görebiliriz. Bu bize bütün kodu tek bir dosyaya yazmamamız için olanak sağlıyor. Peki burada modülün
giriş kodu nerede? Bu da __init__.py
tarafından sağlanıyor.
Python'da herhangi bir dizin içerisinde __init__.py
dosyası varsa, bu dizin modül dizini olarak
kullanılmakta. Dolayısıyla bu örnekte import requests
yazdığımızda bu dizinin içerisindeki
__init__.py
yüklenmekte. Genellikle bu dosya içerisinde diğer import
edilecek satırlar yer
alıyor.
Kendi Modül Dizinimizi (Paketimizi) Oluşturalım¶
matematik.py
dosyası şu anlık işimizi görse de farzedelim ki birçok matematik işlemini ayrı
şekilde tutmak istiyoruz. Bunun için matematik
isimli bir dizin oluşturabiliriz. Dizini oluşturun
ve içerisine __init__.py
adlı bir dosya yerleştirin. Bu dosyanın içerisine yine toplama işlemi
kodunu koyun. Böylelikle dizini modül olarak kullanmış olacağız. Sonrasında matematik.py
dosyasını
silmeyi unutmayın çünkü öncelikli olarak bu yüklenecektir, proje içerisinde olmasını istemiyoruz.
Satırını çalıştırdığımızda artık dizinden okuyacaktır. Dilerseniz burada bir nefeslenelim ve ne yaptığımızın farkında olalım.
- Modül yazmadan
ilkadim.py
örneğini oluşturduk ve toplama işlemi yaptık - Toplama işlemini ayırmak istedik ve
matematik.py
isimli bir dosya oluşturduk - Bu dosyayı
import matematik
şeklinde yükleyip çalıştırdık - Sonrasında bunu bir dizin içerisine aldık ve Python'a dizini modül olarak kullanmasını söyledik
(__init__.py)
__init__.py
içerisine koyduğumuz toplama işlemi kodu aynı şekilde çalıştırabildik ve modül dizini içerisinden bir modül yükleyebildik.
Bunların hepsi Python'un modül yükleme yöntemi ile gerçekleşebildi.
Modül Dizininde Ayrı Modüller¶
Örnek olması açısından bütün kodu __init__.py
içerisine yerleştirdik ancak bu yaptığımız bir
pratik değil. Genellikle bu dosyayı dizini modül dizini olarak kullanmak için boş olarak
yerleştiriyoruz ve içerisine ayrı dosyalar koyuyoruz. Toplama işlemini ayırmak istersek matematik
dizinine topla.py
koymamız gerekmekte. Şimdi __init__.py
içerisine koyduğumuz kodu topla.py
içerisine koyalım ve __init__.py
dosyası boş kalsın. Durum bu şekilde olduğunda modülü yüklemek
için ayrı bir import
kullanmamız gerekecek:
Bu şekilde kullandığımızda matematik
modülünden topla
modülünü programımıza dahil etmiş olduk.
Örneği devam ettirecek olursak carp.py
, bol.py
gibi dosyaları oluşurabilirdik.
Boş ve dolu __init__.py
dosyası
Burada not etmemiz gerekir ki genellikle boş koysak da __init__.py
dosyasının ileri kullanımı
mevcut. Yukarıdaki örnekte from matematik import topla
satırında toplama modülünü direkt
olarak import edebildik ancak import matematik
yazdığımızda Python modül sisteminde öncelikle
__init__.py
yüklendiği için elimize boş bir modül gelecektir. Bunu matematik
modülü import
edilirken birtakım kolaylıklar sağlamak için kullanabiliriz. Bunu da __init__.py
içerisinde
yapıyoruz ancak şu an ileri kullanıma ihtiyacımız yok. Aklımızda durması yeterli.
Sonuç¶
Python modül yapısının nasıl olduğunu, dosyadan ve dizinden nasıl yüklendiğini ve kendi modülümüzü nasıl oluşturacağımızı gördük. Modül yapısının daha fazla incelikleri var ancak şimdilik bunlar bizim için yeterli. Artık kod yazarken modüllere dikkat edip, neyin nerede olduğunun daha fazla farkında olacağız. Bundan sonrasında herhangi bir projeye baktığımızda modüllerin nerede olduğunu ve neyin nasıl çağrıldığını bilerek hareket edeceğiz. Bu bize kodu anlamada zaman kazandıracaktır.
Modül yükleme detaylarını merak ediyorsanız bundan sonrası için Python belgelerine göz atabilirsiniz.