Python'da Kendi Modülünüzü ve Paketinizi Yazma
Beceri rehberi

Python'da Kendi Modülünüzü ve Paketinizi Yazma

Hazırlayan: Mindset Institute EditörlüğüGüncellendi: 5 dk okuma

Kodunuzu dosyalara ve klasörlere bölmeyi, import'un nerede arama yaptığını, __init__.py dosyasının görevini ve __name__ kontrolünü örneklerle öğrenirsiniz. Mutlak ve göreli import farkını da görürsünüz.

Bir bakışta

  1. Modül, bir .py dosyasıdır; paket, modülleri toplayan klasördür. Modülün adı dosya adıdır; paket yolları nokta ile yazılır.
  2. Her modül bir oturumda yalnız bir kez içe aktarılır. Dosyayı değiştirdikten sonra çalışan oturumda yeniden yüklemek ya da yeniden başlatmak gerekir.
  3. Python modülü önce çalışan betiğin klasöründe arar. Bu yüzden yerel dosyanızın adı standart bir modülle çakışırsa onu gölgeleyebilir.
  4. __init__.py, klasörü paket olarak işaretler. Boş olabilir ya da paketin başlangıç kodunu taşıyabilir.
  5. Göreli import yalnız paket içinden çalışır. Betik olarak doğrudan çalıştırılan dosyada mutlak import kullanılmalıdır.

Modül nedir, nasıl yazılır

Python belgelerine göre modül, tanımlar ve ifadeler içeren bir Python dosyasıdır. Dosya adı .py uzantısı çıkarılmış hâliyle modülün adı olur. Kodunuz büyüdükçe fonksiyonları ve sınıfları ayrı dosyalara bölmek, tekrar kullanımı ve okunurluğu kolaylaştırır.

metin.py dosyasını oluşturalım:

def temizle(metin): """Baştaki ve sondaki boşlukları atar, küçük harfe çevirir.""" return metin.strip().lower()

Başka bir dosyadan bu modülü içe aktarmak için import kullanırsınız:

import metin print(metin.temizle(' Merhaba '))

Her modülün kendi özel isim alanı vardır; bu sayede iki modülde aynı adlı bir fonksiyon çakışmaz. Bir modülün üst düzeydeki ifadeleri, oturumda ilk içe aktarıldığında bir kez çalışır. Belgelere göre her modül bir oturumda yalnız bir kez içe aktarılır; dosyayı düzenledikten sonra etkileşimli oturumda değişikliği görmek için yorumlayıcıyı yeniden başlatmak ya da importlib.reload kullanmak gerekir.

import biçimleri

Bir modülden ne almak istediğinize göre birkaç biçim vardır.

import metin # metin.temizle(...) yazarsınız from metin import temizle # temizle(...) yazarsınız import metin as m # m.temizle(...) yazarsınız from metin import temizle as t # t(...) yazarsınız from metin import * # önerilmez

import modul biçimi yalnızca modül adını getirir; içindekilere modül.ad ile erişirsiniz. from modul import ad ise seçtiğiniz adları doğrudan isim alanınıza ekler. as ile kısa takma ad verebilirsiniz.

from modul import * biçimi, alt çizgiyle başlamayan tüm genel adları getirir. Python belgeleri bu biçimin kodda önerilmediğini belirtir: neyin içeri girdiği belirsizleşir ve var olan adlarınızı sessizce ezebilir. Açıkça gereken adları içe aktarmak hem okuyanı hem aracınızı rahatlatır.

Python modülü nerede arar

İçe aktarma isteği geldiğinde Python önce yerleşik modüllere bakar. Bulamazsa sys.path listesindeki klasörleri sırayla tarar. Belgelere göre bu liste çalışan betiğin klasöründen (ya da geçerli klasörden), sonra PYTHONPATH ortam değişkeninden, sonra da kurulumun varsayılan klasörlerinden başlatılır; paketlerin kurulduğu site-packages klasörü de buna dahildir.

Bu sıranın pratik bir sonucu vardır: betiğin klasörü standart kütüphaneden önce gelir. Kendi dosyanıza random.py ya da json.py gibi standart bir modülün adını verirseniz, Python sizin dosyanızı bulur ve standart modül gölgelenir. Beklenmedik hata mesajlarının sık nedeni budur. Modüllerinize standart kütüphaneyle çakışmayan adlar verin.

Modülü başka bir klasörden kullanmak isterseniz sys.path'e klasör ekleyebilirsiniz, ama kalıcı çözüm kodu paket hâline getirmek ve düzgün kurmaktır. Python derlenmiş kodu __pycache__ klasöründe önbelleğe alır; bu klasörü elle düzenlemeniz gerekmez.

Paket oluşturma ve __init__.py

Paket, modülleri noktalı adlarla gruplayan bir klasör yapısıdır. Belgelere göre __init__.py dosyası, bir klasörün normal paket olarak tanınmasını sağlar. Dosya boş olabilir, paketin başlangıç kodunu çalıştırabilir ya da __all__ listesini tanımlayabilir.

proje/ main.py araclar/ __init__.py metin.py sayi.py

Bu yapıda araclar bir paket, metin ve sayi onun modülleridir. main.py içinden şöyle içe aktarırsınız:

import araclar.metin from araclar import metin from araclar.metin import temizle

Üç biçim de aynı modüle ulaşır; fark, adı nasıl kullanacağınızdır. import a.b.c yazarken son parça dışındaki her parça paket olmalıdır.

__init__.py içine paketin en çok kullanılan adlarını alıp yüzeyi sadeleştirebilirsiniz:

from .metin import temizle

Böylece kullanıcı from araclar import temizle yazabilir ve iç dosya yapısını bilmek zorunda kalmaz. __all__ tanımladığınızda from paket import * bu listedeki alt modülleri getirir; tanımlamazsanız yalnızca __init__.py içinde tanımlı adlar ve daha önce içe aktarılmış alt modüller gelir.

Şekil 1

Kod önce modüle, modüller de pakete toplanır

  1. Fonksiyon ve değişkenlerTek bir işi yapan kod parçaları.
  2. ModülBu parçaları toplayan bir .py dosyası.
  3. PaketModülleri __init__.py ile gruplayan klasör.
Kaynak: Python belgeleri: ModulesMindset Institute

Mutlak ve göreli import

Paket içindeki bir modül başka bir modüle iki şekilde ulaşabilir. Mutlak import, paketin tam yolunu yazar: from araclar import metin. Göreli import ise baştaki noktalarla bulunduğunuz paketi kullanır: tek nokta geçerli paketi, çift nokta üst paketi temsil eder.

from . import metin from .metin import temizle from .. import ortak

Belgelere göre mutlak import her zaman çalışır. Göreli import ise modülün paket içindeki adına dayanır. Bu yüzden doğrudan betik olarak çalıştırılan bir dosyada (adı __main__ olduğu için paketi yoktur) göreli import çalışmaz, mutlak import kullanmak gerekir. Paket içindeki modülü doğrudan çalıştırmak isterseniz python -m araclar.metin gibi paket yoluyla başlatmak bu soruna çözüm olur.

Belgeler from paket import alt_modul yazımını önerilen biçim olarak gösterir. Göreli import kullanıyorsanız paket yapısını taşıdığınızda yolları yeniden gözden geçirin. Aynı projede ikisini karıştırmak okunurluğu düşürür, birini seçip tutarlı kalın.

Şekil 2

Mutlak import her yerde çalışır, göreli import paket içinde

Mutlak importGöreli import
Yazımfrom araclar import metinfrom . import metin
Dayandığı şeyPaketin tam yoluModülün paket içindeki konumu
Betik olarak çalıştırıncaÇalışırPaket olmadığı için çalışmaz
TaşırkenPaket yolu aynı kaldıkça etkilenmezYapı değişince yolları gözden geçirin
Kaynak: Python belgeleri: ModulesMindset Institute

__name__ == '__main__' kalıbı

Bir dosya hem doğrudan çalıştırılabilsin hem de başka dosyalara modül olarak aktarılabilsin istiyorsanız __name__ kontrolünü kullanırsınız. Belgelere göre dosyayı doğrudan çalıştırdığınızda __name__ değeri __main__ olur; içe aktarıldığında ise modülün adı olur.

def temizle(metin): return metin.strip().lower()

if __name__ == '__main__': print(temizle(' Deneme '))

Bu dosyayı çalıştırınca deneme çıktısı görülür. Başka bir dosya aynı dosyayı import ettiğinde ise yalnızca fonksiyon tanımlanır, deneme satırı çalışmaz. Böylece betik yazarken test ve örnek çağrıları aynı dosyada tutabilir, ama modülü kullanan kişiye istenmeyen çıktı vermezsiniz.

Komut satırı betiklerinde de ana akışı bir main fonksiyonuna koyup bu kontrolün altında çağırmak yaygın bir alışkanlıktır.

Sık yapılan hatalar

  • __init__.py unutmak: klasör beklediğiniz gibi paket olarak çalışmayabilir.
  • Standart modül adı vermek: kendi dosyanız gerçek modülü gölgeler.
  • from modul import * kullanmak: hangi adların geldiği belirsizleşir.
  • Betiği paket içinden doğrudan çalıştırıp göreli import kullanmak: paket bilgisi olmadığından hata alınır.
  • Döngüsel import: iki modül birbirini içe aktarıyorsa yapıyı yeniden düzenleyin.
  • Değişiklik sonrası eski modülü görmek: oturumu yeniden başlatın ya da modülü yeniden yükleyin.
  • Her şeyi tek dosyada tutmak: bir noktadan sonra bakımı zorlaşır, modüllere ayırın.

Bu beceriyi Mindset programlarında nerede çalışırsınız

Python ile Programlama Eğitimi, Modüller ve Paketler başlıklı modülü içerir; kod organizasyonu, standart kütüphaneden içe aktarma ve kendi paketini yazma bu akışta yer alır. Betikleri bir araya toplamak, ekip içinde ortak yardımcı kod yazmak ya da otomasyonları düzenli bir projeye dönüştürmek isteyen kişiler için modül ve paket yapısı ilk adımdır.

İlgili Mindset programı

Python ile Programlama Eğitimi

Sık sorulanlar

Sık sorulan sorular

Her klasör için __init__.py yazmam gerekir mi?

Normal paketler için evet, belgeler __init__.py'nin klasörü paket olarak işaretlediğini söyler. Belgelerde ayrıca __init__.py gerektirmeyen ad alanı paketleri gelişmiş bir istisna olarak anılır. Başlangıç için her pakete bir __init__.py koymak güvenlidir.

import ile from import arasında hangisini seçmeliyim?

Modülün adını kodda görünür tutmak istiyorsanız import modul; yalnız birkaç adı sık kullanacaksanız from modul import ad uygundur. Belirsizlik yarattığı için from modul import * kodda önerilmez; hangi adların geldiği açık kalmalıdır.

Kendi modülüm neden bulunamıyor?

Python modülü sys.path içindeki klasörlerde arar. Dosyanız bu klasörlerden birinde değilse bulunamaz. Betiği modülün bulunduğu klasörden çalıştırın, paketi düzgün kurun ya da sys.path'e klasörü ekleyin; en sağlam çözüm paketleyip kurmaktır.

__name__ == '__main__' neden gerekli?

Aynı dosyanın hem betik hem modül olarak kullanılmasını sağlar. Doğrudan çalıştırınca __name__ değeri __main__ olur; içe aktarılınca modül adı olur. Böylece test ya da örnek çağrılar yalnızca doğrudan çalıştırmada devreye girer.

Modülü değiştirdim ama eski hali çalışıyor, ne yapmalıyım?

Belgelere göre her modül bir oturumda yalnız bir kez içe aktarılır. Etkileşimli oturumda yorumlayıcıyı yeniden başlatın ya da importlib.reload ile modülü yeniden yükleyin. Betik olarak çalıştırıyorsanız programı yeniden başlatmak yeterlidir.

Python Modül ve Paket Oluşturma: import Rehberi