---
title: 'Paket Yöneticileri'
source: 'https://academia.sh/tr/kurslar/python-projeleri/paket-yoneticileri'
course: 'Python Projeleri: Paketleme ve Test'
language: tr
updated: '2026-08-17T18:10:31+00:00'
license: 'CC BY-SA 4.0'
---

# Paket Yöneticileri

Paketler birbirini gerektirdiğinde aynı bildirim dört strateji altında 4 ayrı küme verir ve bunların yalnız 3'ü tutarlıdır; kısıtlar sıkılaştığında iki geri izlemeli strateji çözüm bulamaz ve tutarlı küme sayısı 0'a iner, kilit dosyası ise dördünü de 1'e indirir.

Önceki dersin ölçümünde her paket kendi aralığından bağımsız seçildi; seçimler birbirine
hiç bakmadı. O varsayım tabloyu okunur kıldı ama gerçeği eksik bıraktı: kurulan paketlerin
de kendi bildirimleri vardır ve bunlar birbiriyle çelişebilir.

Bu ders o kısıtları tabloya koyar. Sorusu iki katmanlıdır: **aynı bildirim, paket gerekleri
de hesaba katıldığında hangi kümeleri veriyor**, ve bir strateji çelişkili bir küme
seçtiğinde bu nereden görülüyor? Yanıtın ikinci yarısı ilkinden önemli çıkacak.

## Paket Yöneticisi Ne Yapar

**Paket yöneticisi** bir araç sınıfının adıdır ve bu kurs hiçbir ürün adı yazmaz;
davranışları burada **modellenmiştir**. Yaptığı iş dört adıma ayrılır: bildirimi okumak,
depodan aday sürümleri toplamak, adaylar arasından bir küme seçmek, seçilen kümeyi siteye
kurmak. Bu dersin ilgilendiği adım üçüncüsüdür.

Dördüncü adımın nereye yazdığı ilk derste kuruldu: yalıtılmış bir sitede kurulum yalnız o
projenin gördüğünü değiştirir, paylaşılan bir sitede ise komşuların gördüğünü de. Bu ders
sitenin yalıtılmış olduğunu varsayar ve o eksene bir daha dönmez; buradaki bütün ayrı
sonuçlar tek bir sitenin içinde doğar.

Üçüncü adımın tek başına bir adı vardır: **çözümleme (resolution)**. Girdisi bir aralık
listesi ve bir aday havuzudur; çıktısı her paket için tam bir sürümdür. Arada duran şey,
paket yöneticisinin **çözümleme stratejisidir** ve önceki derste gösterildiği gibi bu
strateji bildirimde yazmaz.

Sürüm numarasının bölümlerinin ne anlattığı ve anlamlı sürümleme, **Sürüm Kontrolüne
Giriş** kursundaki etiketleme dersinde kuruldu; burada tekrarlanmaz. Buradaki soru sürüm
numarasının ne söylediği değil, **aralıkların birlikte hangi kümeleri mümkün kıldığıdır**.

## Gerek Tablosu ve Tutarlılık

Kurguya tek bir ekleme yapılır: bir **gerek tablosu**. Tablo, her paket sürümünün hangi
paketten hangi aralığı istediğini yazar. Depo ve projenin bildirimi ortak tanımdan birebir
gelir ve değişmez; eklenen şey paketlerin kendi istekleridir.

Tablonun kurguda kurduğu gerilim tek cümleyle okunur: `olcum`'un yeni sürümleri `ortak`'ın
yeni sürümlerini ister, `rapor`'un yeni sürümü ise `ortak`'ın eski sürümlerini. İkisini de
en yeni haliyle isteyen bir kurulum, `ortak` için aynı anda iki ayrı şey istemiş olur.

Buradan ölçümün ikinci kavramı doğar. Bir küme **tutarlıdır** ancak ve ancak seçilen her
sürümün gereği, kümedeki öbür seçimlerce karşılanıyorsa. Tutarlılık kurulumun başarısıyla
aynı şey değildir: tutarsız bir küme de siteye kurulabilir, çünkü kurulum bir dosya
yazmadır ve gerek tablosunu okumak zorunda değildir.

## Dört Strateji

Ölçüm dört strateji karşılaştırır. İlk ikisi **bağımsız** seçicidir: her paketi kendi
aralığının bir ucundan alır ve gerek tablosuna hiç bakmaz — önceki dersin iki stratejisi
budur. Kalan ikisi **geri izlemelidir**: bir sürüm seçer, kısıtları sınar, tutmadığında geri
döner ve başka bir sürüm dener.

Geri izlemeli iki stratejinin farkı yalnız **arama sırasıdır**: hangi paketin sürümüne önce
karar verildiği. Aynı bildirim, aynı gerek tablosu, aynı depo — değişen tek şey sıradır. Bu
fark ölçümün en önemli satırını üretecek.

Ölçümün varsayımları:

- **OB24** — Depo, bildirim ve aralık kuralı ortak tanımdan birebir alınır; ders ikisinin de
  davranışını değiştirmez. Eklenen tek şey gerek tablosudur.
- **OB25** — Gerek tablosu kurgudur ve kâhinin parçasıdır: hangi sürümün neyi istediğini biz
  yazdık, bu yüzden her kümenin tutarlı olup olmadığı ölçmeden bilinir.
- **OB26** — Bir paket sürümü en çok bir gerek taşır ve gerek bir aralıktır. Zincirin
  derinliği bir düzeydir; daha derin zincirler sayıyı büyütür, kuralı değiştirmez.
- **OB27** — Bağımsız stratejiler gerek tablosunu **okumaz**. Kurdukları küme tutarsız
  olabilir ve kurulum yine tamamlanır.
- **OB28** — Geri izleme, arama sırasındaki her pakete adayları strateji yönünde dener ve
  kısmi kümeyi her adımda sınar. İlk tutarlı tam kümeyi döndürür.
- **OB29** — Kısmi kümenin sınanmasında yalnız **iki ucu da seçilmiş** gerekler denetlenir;
  hedefi henüz seçilmemiş bir gerek o adımda ihlal sayılmaz.
- **OB30** — İki arama sırası denenir: `olcum, ortak, rapor` ve `rapor, ortak, olcum`.
  Sıra bir yapılandırma ayrıntısıdır; proje onu bildirimde yazmaz.
- **OB31** — Sıkı gerek tablosu, aynı depoda `olcum`'un bütün uygun sürümlerinin `ortak`'ın
  en yeni sürümünü, `rapor`'un bütün uygun sürümlerinin ise daha eskisini istemesiyle
  türetilir. Kesişimi boş olan bir bildirim kümesini modeller.
- **OB32** — Çözüm bulunamadığında geri izleme `None` döndürür ve bu bir **hata değil,
  ölçümün bir sonucudur**: tutarlı küme sayısı sıfırdır.
- **OB33** — Kilit, tutarlı kümelerden birinin — geri izlemeli en yeni stratejisinin
  sonucunun — kopyasıdır. Kilit varken çözümleme çağrılmaz.
- **OB34** — Sürüm numaraları kurgu paketlerin kurgu sürümleridir.
- **OB35** — **Gerçek kurulum yapılmaz, gerçek paket indirilmez;** çözümleme bir sözlük
  döndürür.
- **OB36** — Süre ölçülmez. Sayılan şey **ayrı küme**, **ayrı tutarlı küme** ve kilitli
  kurulumun verdiği **ayrı sonuç** sayısıdır.

## Ölçüm

```python
"""Cozumleme stratejileri: ayni bildirim, ayri kume; cakisma dogdugunda ne oluyor."""

DEPO = {
    "olcum": [(1, 0), (1, 1), (1, 2), (2, 0)],
    "rapor": [(0, 9), (1, 0), (1, 1)],
    "ortak": [(3, 0), (3, 1), (3, 2), (4, 0)],
}
BILDIRIM = {"olcum": ((1, 0), (2, 0)), "rapor": ((1, 0), (2, 0)),
            "ortak": ((3, 0), (4, 0))}
PAKETLER = ("olcum", "ortak", "rapor")

# Paketlerin kendi bagimliliklari: surum -> (hedef paket, alt, ust)
GEREK = {
    ("olcum", (1, 0)): ("ortak", (3, 0), (4, 0)),
    ("olcum", (1, 1)): ("ortak", (3, 1), (4, 0)),
    ("olcum", (1, 2)): ("ortak", (3, 2), (4, 0)),
    ("rapor", (0, 9)): ("ortak", (3, 0), (3, 1)),
    ("rapor", (1, 0)): ("ortak", (3, 0), (4, 0)),
    ("rapor", (1, 1)): ("ortak", (3, 0), (3, 2)),
}
# Ayni depo, daha sikici bir gerek tablosu: olcum'un uc surumu de yeni ortak istiyor.
SIKI = dict(GEREK)
SIKI[("olcum", (1, 0))] = ("ortak", (3, 2), (4, 0))
SIKI[("olcum", (1, 1))] = ("ortak", (3, 2), (4, 0))
SIKI[("rapor", (1, 0))] = ("ortak", (3, 0), (3, 2))


def uygun(paket):
    alt, ust = BILDIRIM[paket]
    return [s for s in DEPO[paket] if alt <= s < ust]


def coz(strateji="en yeni"):
    """Bagimsiz secim: her paket kendi araliginin ucundan alinir."""
    secim = {}
    for paket in sorted(BILDIRIM):
        adaylar = uygun(paket)
        secim[paket] = adaylar[-1] if strateji == "en yeni" else adaylar[0]
    return secim


def tutarli(secim, gerek):
    """Secilen surumlerin gerekleri, secilmis olan paketlerce karsilaniyor mu."""
    for paket, surum in secim.items():
        k = gerek.get((paket, surum))
        if k is None:
            continue
        hedef, alt, ust = k
        if hedef in secim and not alt <= secim[hedef] < ust:
            return False
    return True


def geri_izle(sira, gerek, strateji="en yeni"):
    """Cakisma dogdugunda geri donup baska surum dener; sira arama sirasidir."""
    def ilerle(i, secim):
        if i == len(sira):
            return dict(secim)
        paket = sira[i]
        adaylar = uygun(paket)
        if strateji == "en yeni":
            adaylar = adaylar[::-1]
        for surum in adaylar:
            secim[paket] = surum
            if tutarli(secim, gerek):
                sonuc = ilerle(i + 1, secim)
                if sonuc is not None:
                    return sonuc
            del secim[paket]
        return None
    return ilerle(0, {})


def yazim(secim):
    if secim is None:
        return f"{'çözüm yok':>23s}"
    return " ".join(f"{'.'.join(map(str, secim[p])):>7s}" for p in PAKETLER)


def kur(kilit_dosyasi, islev, gerek):
    """Kilit varsa cozumleme yapilmaz; yoksa karari strateji verir."""
    return dict(kilit_dosyasi) if kilit_dosyasi else islev(gerek)


STRATEJILER = (
    ("bağımsız, en yeni", lambda g: coz("en yeni")),
    ("bağımsız, en eski", lambda g: coz("en eski")),
    ("geri izlemeli, en yeni", lambda g: geri_izle(("olcum", "ortak", "rapor"), g)),
    ("geri izlemeli, rapor önce", lambda g: geri_izle(("rapor", "ortak", "olcum"), g)),
)


def tablo(baslik, gerek):
    print(f"{baslik:<26s} {'olcum':>7s} {'ortak':>7s} {'rapor':>7s}  tutarlı")
    kumeler, saglam = [], []
    for ad, islev in STRATEJILER:
        secim = islev(gerek)
        durum = secim is not None and tutarli(secim, gerek)
        if secim is not None:
            kumeler.append(tuple(sorted(secim.items())))
            if durum:
                saglam.append(tuple(sorted(secim.items())))
        print(f"{ad:<26s} {yazim(secim)}  {'evet' if durum else 'hayır':>7s}")
    print(f"dört strateji: {len(set(kumeler))} ayrı küme, "
          f"{len(set(saglam))} ayrı tutarlı küme")


tablo("gerek tablosu", GEREK)
print()
tablo("sıkı gerek tablosu", SIKI)
print()
kilit_dosyasi = geri_izle(("olcum", "ortak", "rapor"), GEREK)
kilitli = {tuple(sorted(kur(kilit_dosyasi, islev, GEREK).items()))
           for _, islev in STRATEJILER}
print("kilide yazılan küme:      " + yazim(kilit_dosyasi))
print(f"kilit dosyası varken dört strateji: {len(kilitli)} ayrı küme")
```

```
gerek tablosu                olcum   ortak   rapor  tutarlı
bağımsız, en yeni              1.2     3.2     1.1    hayır
bağımsız, en eski              1.0     3.0     1.0     evet
geri izlemeli, en yeni         1.2     3.2     1.0     evet
geri izlemeli, rapor önce      1.1     3.1     1.1     evet
dört strateji: 4 ayrı küme, 3 ayrı tutarlı küme

sıkı gerek tablosu           olcum   ortak   rapor  tutarlı
bağımsız, en yeni              1.2     3.2     1.1    hayır
bağımsız, en eski              1.0     3.0     1.0    hayır
geri izlemeli, en yeni                   çözüm yok    hayır
geri izlemeli, rapor önce                çözüm yok    hayır
dört strateji: 2 ayrı küme, 0 ayrı tutarlı küme

kilide yazılan küme:          1.2     3.2     1.0
kilit dosyası varken dört strateji: 1 ayrı küme
```

## Dört Strateji, Dört Küme

Üst tablonun dört satırı **4 ayrı küme** veriyor ve dördü de aynı bildirimden çıkıyor. Bu,
önceki dersin iki kümesinin üstüne iki tane daha ekliyor; eklenen ikisi bağımsız seçimin
ulaşamayacağı kümeler.

İlk satır kursun bu dersteki asıl bulgusudur. Bağımsız `en yeni` stratejisi
`1.2 / 3.2 / 1.1` kümesini seçiyor ve bu küme **tutarsız**: `rapor 1.1`, `ortak` için
`3.2`'den eskisini istiyor, ama kümede `ortak 3.2` var. Buna karşın kurulum tamamlanıyor. Hiçbir hata iletisi doğmuyor,
çünkü bağımsız strateji gerek tablosunu hiç okumadı. Sonuç, sitede duran ve birbirini
istemeyen üç paket.

İkinci satır bağımsız `en eski` stratejisinin tesadüfen tutarlı bir küme kurduğunu
gösteriyor. Tesadüf sözcüğü burada tam yerindedir: strateji yine gerek tablosunu okumadı,
yalnızca aralıkların alt uçları çakışmadı. Aynı strateji başka bir tabloyla tutarsız bir
küme kurardı — nitekim alt tabloda kuruyor.

Son iki satır geri izlemeli stratejileri veriyor ve ikisi de tutarlı, ama **ayrı**:
`1.2 / 3.2 / 1.0` ile `1.1 / 3.1 / 1.1`. İkisi arasında tek fark arama sırasıdır — hangi
paketin sürümüne önce karar verildiği. Bildirim aynı, depo aynı, kısıtlar aynı; yine de iki
ayrı meşru kurulum. Bu satır, **çözümleyicinin kendisinin bir ayrı sonuç ekseni olduğunu**
söylüyor: aracı değiştirmek, bildirimi değiştirmeden kurulumu değiştirebilir.

Toplam: dört strateji, **4 ayrı küme**, bunların **3'ü tutarlı**.

## Çakışma Nereye Yazılır

Alt tablo kısıtları sıkılaştırıyor: bu tabloda `olcum`'un bütün uygun sürümleri `ortak`'ın
en yenisini, `rapor`'un bütün uygun sürümleri ise daha eskisini istiyor. İki isteğin
kesişimi boş.

Geri izlemeli iki strateji de **çözüm yok** döndürüyor. Tutarlı küme sayısı **0**. Bu bir
başarısızlık gibi görünür ve bir anlamda öyledir — ama ölçümün asıl bulgusu üstteki iki
satırdadır: bağımsız stratejiler yine bir küme döndürüyor. Aynı çelişki, okuyan araca göre
ya bir ret ya sessiz bir kurulum üretiyor.

İkisi arasındaki fark, hatanın **nerede görüneceğidir**. Ret, çözümleme anında görünür ve
elde bir bilgi bırakır: bu bildirim kümesi çelişkilidir, ya bir aralık gevşetilecek ya bir
paket değiştirilecektir. Sessiz kurulum ise hiçbir şey bırakmaz; çelişki siteye kurulur ve
ancak çalışma zamanında, çelişen iki paketin karşılaştığı satırda ortaya çıkar. Ve o satıra
her koşumda uğranmaz.

Ölçünün diliyle: ret **0 ayrı sonuç** üretir ve sıfır, sayılabilir bir yanıttır. Sessiz
kurulum **1 ayrı sonuç** üretir ama o sonucun geçerli olup olmadığını ölçmez. Bir
çözümleyicinin çözemediğini söylemesi, çözemediğini söylememesinden bilgi açısından
üstündür.

## Çözümleyicinin Kendisi Yeniden Üretilebilir mi

Ölçüm dört stratejiyi karşılaştırdı, ama her stratejinin **kendi içinde** kaç sonuç
verdiğini de sormak gerekir. Modeldeki dört stratejinin dördü de belirlenimcidir: aday
listesi depodan sıralı gelir, arama sırası sabittir, hiçbir yerde rastgelelik yoktur. Aynı
strateji aynı girdiyle çağrıldığında **1 ayrı sonuç** verir.

Bu, bir çözümleyiciden istenecek en temel özelliktir ve kendiliğinden gelmez. Aday havuzu
birden çok kaynaktan toplanıyorsa hangi kaynağın önce yanıtladığı sıraya karışabilir; bir
önbellek ısındığında aynı sorgu ayrı bir liste döndürebilir; paralel indirme kurulum
sırasını değiştirebilir. Bunların hiçbiri stratejinin kuralını değiştirmez, ama hepsi
**girdisini** değiştirir — ve girdisi değişen bir kural ayrı bir küme verir.

Bu yüzden bir çözümleyicinin sözü iki katmanlıdır. Birinci katman kuraldır: hangi aday
seçilir. İkinci katman kuralın girdisidir: adayların hangi düzende, hangi kaynaktan ve
hangi anda toplandığı. Yeniden üretilebilir bir kurulum ikisini birden sabitlemeyi
gerektirir, ve ikinci katmanı yazıya geçiren belge kilit dosyasıdır.

## Kilidin Bu Tablodaki Yeri

Son iki satır önceki dersin sonucunu bu tablonun üstüne koyuyor. Tutarlı kümelerden biri —
geri izlemeli en yeni stratejisinin bulduğu `1.2 / 3.2 / 1.0` — kilide yazıldığında dört
strateji de aynı kümeyi kuruyor: **1 ayrı sonuç**.

Kilidin burada kapattığı eksen yenidir. Önceki derste kapatılanlar strateji yönü ve deponun
zamanıydı; burada kapatılan **çözümleyicinin kendisi**. Kilit yazıldıktan sonra hangi paket
yöneticisinin kullanıldığı sonucu değiştirmiyor, çünkü çözümlenecek bir şey kalmadı.

Bu, kilidin ne kadar iş yaptığını da sınırlıyor. Kilit, kilidi üreten çözümleyicinin
kararını taşır; iyi bir kararı da kötü bir kararı da aynı sadakatle. Üstteki tabloda üç
tutarlı kümeden hangisinin kilide yazıldığı, kilide bakılarak anlaşılmaz — kilit yalnız
seçileni yazar, seçme gerekçesini değil.

## Özet

- **Paket yöneticisi** bir araç sınıfıdır; işi bildirimi okumak, aday toplamak, bir küme
  seçmek ve kurmaktır. Ayrı sonucu üreten adım seçme adımıdır.
- Paketlerin kendi gerekleri hesaba katıldığında aynı bildirim dört strateji altında
  **4 ayrı küme** verir ve bunların **3'ü tutarlıdır**.
- Bağımsız seçim gerek tablosunu okumaz: `1.2 / 3.2 / 1.1` kümesi **tutarsız** olduğu halde
  kurulur ve hiçbir uyarı üretmez.
- İki geri izlemeli strateji ayrı **arama sırası** yüzünden iki ayrı tutarlı küme verir;
  çözümleyicinin kendisi bir ayrı sonuç eksenidir.
- Kesişimi boş kısıtlarda geri izleme **0 tutarlı küme** döndürür; ret çözümleme anında
  bilgi bırakır, sessiz kurulum ise çelişkiyi çalışma zamanına erteler.
- Kilit dosyası dört stratejiyi **1 ayrı sonuca** indirir, ama yazdığı kararın hangi
  gerekçeyle seçildiğini taşımaz.

## Sonraki Adım

Bu dersin bütün kümeleri tek bir yorumlayıcı varsayıldığı için karşılaştırılabildi. O
varsayım da tıpkı önceki iki varsayım gibi yazılı değildi. Sonraki ders onu ölçüme sokar:
aynı proje, aynı bildirim, ayrı yorumlayıcı sürümleri. Sorulacak olan şudur — çözümleme
yorumlayıcıya göre kaç ayrı küme veriyor, ve bir yorumlayıcıda üretilmiş kilit dosyası bir
başkasında ne yapıyor?
