Poetry ile Modern Python Proje ve Bağımlılık Yönetimi

Python projelerinde bağımlılık yönetimi, yıllar boyunca sysadminlerin ve geliştiricilerin başını ağrıtan bir konu oldu. pip, virtualenv, requirements.txt üçlüsüyle bir şekilde idare ettik ama “benim makinemde çalışıyor” problemi hiç gitmedi. İşte tam bu noktada Poetry sahneye giriyor ve oyunun kurallarını değiştiriyor.

Poetry Nedir ve Neden Önemli?

Poetry, Python projeleri için bağımlılık yönetimi, paket oluşturma ve yayınlama işlemlerini tek çatı altında toplayan modern bir araç. Sadece bağımlılıkları yönetmekle kalmıyor, sanal ortamı otomatik oluşturuyor, pyproject.toml standardını kullanarak projeyi tanımlıyor ve bağımlılık çözümlemesini deterministik hale getiriyor.

Klasik pip + requirements.txt yaklaşımının temel sorunu şu: requirements.txt içinde requests==2.28.0 yazıyorsunuz ama requestsin kendi bağımlılıklarının versiyonlarını belirtmiyorsunuz. Bir geliştirici farklı, CI/CD pipeline farklı, production farklı versiyonlar çekebiliyor. Poetry bu sorunu poetry.lock dosyasıyla çözüyor. Bu dosya her bağımlılığın tam versiyonunu, alt bağımlılıklarını ve hash değerlerini saklıyor.

Kurulum

Poetry’nin kurulumu için resmi installer’ı kullanmak en sağlıklı yol. pip install poetry yapabilirsiniz ama bu yöntem Poetry’nin kendi bağımlılıklarını projenizin ortamıyla karıştırma riski taşıyor.

# Linux/macOS için resmi kurulum
curl -sSL https://install.python-poetry.org | python3 -

# Kurulumu doğrula
poetry --version

# PATH'e eklemek için (bash kullanıcıları)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

# Windows PowerShell için
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python -

Kurulum sonrası shell tamamlamayı aktif etmek günlük kullanımı kolaylaştırıyor:

# Bash için
poetry completions bash >> ~/.bash_completion

# Zsh için
poetry completions zsh > ~/.zfunc/_poetry
# .zshrc içine şunu ekleyin: fpath+=~/.zfunc

# Fish için
poetry completions fish > ~/.config/fish/completions/poetry.fish

Yeni Proje Oluşturma

Poetry ile yeni proje başlatmak son derece temiz:

# Yeni proje oluştur
poetry new my-web-api

# Oluşan yapı:
# my-web-api/
# ├── pyproject.toml
# ├── README.md
# ├── my_web_api/
# │   └── __init__.py
# └── tests/
#     └── __init__.py

# Mevcut bir dizinde başlatmak için
cd existing-project
poetry init

poetry init komutu interaktif bir sihirbaz başlatıyor ve pyproject.toml dosyasını adım adım oluşturmanıza yardımcı oluyor. Projenin adı, versiyonu, açıklaması, Python versiyon kısıtı gibi bilgileri giriyor, bağımlılıkları ekleyip eklemeyeceğinizi soruyor.

pyproject.toml Dosyasını Anlamak

Bu dosya Poetry projelerinin kalbi. PEP 518 ile standart hale gelen pyproject.toml, projenin tüm metadata bilgisini ve bağımlılık tanımlarını barındırıyor:

[tool.poetry]
name = "my-web-api"
version = "0.1.0"
description = "Production-grade REST API servisi"
authors = ["Ahmet Yilmaz <[email protected]>"]
readme = "README.md"
packages = [{include = "my_web_api"}]

[tool.poetry.dependencies]
python = "^3.11"
fastapi = "^0.104.0"
uvicorn = {extras = ["standard"], version = "^0.24.0"}
sqlalchemy = "^2.0.0"
pydantic-settings = "^2.0.0"
redis = "^5.0.0"

[tool.poetry.group.dev.dependencies]
pytest = "^7.4.0"
pytest-asyncio = "^0.21.0"
black = "^23.0.0"
ruff = "^0.1.0"
mypy = "^1.0.0"

[tool.poetry.group.staging.dependencies]
locust = "^2.17.0"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Versiyon kısıtlamalarındaki sembollere dikkat etmek gerekiyor:

  • ^1.2.3: 1.x.x aralığında güncellemeye izin verir, 2.0.0’a geçmez (caret)
  • ~1.2.3: Sadece patch güncellemelerine izin verir, 1.3.0’a geçmez (tilde)
  • >=1.2.3,<2.0.0: Açık aralık tanımı
  • 1.2.3: Tam versiyon kilidi
  • *: Herhangi bir versiyon (önerilmez)

Bağımlılık Ekleme ve Kaldırma

# Production bağımlılığı ekle
poetry add fastapi

# Belirli versiyon kısıtıyla ekle
poetry add "sqlalchemy>=2.0,<3.0"

# Extra özelliklerle ekle
poetry add "uvicorn[standard]"

# Geliştirme bağımlılığı ekle
poetry add --group dev pytest black ruff

# Opsiyonel bağımlılık ekle
poetry add --optional psycopg2

# Bağımlılık kaldır
poetry remove requests

# Dev bağımlılığı kaldır
poetry remove --group dev pylint

# Bağımlılıkları güncelle
poetry update

# Sadece belirli paketi güncelle
poetry update fastapi

# En son uyumlu versiyona yükselt (kısıtları görmezden gel)
poetry add fastapi@latest

Sanal Ortam Yönetimi

Poetry sanal ortamları otomatik olarak yönetiyor ama davranışı yapılandırabilirsiniz:

# Sanal ortam bilgisini görüntüle
poetry env info

# Mevcut sanal ortamları listele
poetry env list

# Belirli Python versiyonu ile sanal ortam oluştur
poetry env use python3.11

# Sanal ortamı proje içinde oluştur (önerilir)
poetry config virtualenvs.in-project true

# Bu ayarı yaptıktan sonra install çalıştır
poetry install

# Sanal ortamı sil
poetry env remove python3.11

# Sanal ortama gir
poetry shell

# Sanal ortamdan çık
exit

# Shell'e girmeden komut çalıştır
poetry run python -m pytest
poetry run uvicorn my_web_api.main:app --reload

virtualenvs.in-project true ayarı proje dizininde .venv klasörü oluşturuyor. Bu yaklaşım özellikle IDE entegrasyonu açısından çok daha temiz çünkü VS Code, PyCharm gibi editörler sanal ortamı otomatik olarak buluyor.

Gerçek Dünya Senaryosu: Mikro Servis Projesi

Birden fazla ortamı olan bir API projesi düşünelim. Geliştirme, staging ve production ortamları için farklı bağımlılık grupları tanımlayalım:

# Projeyi başlat
poetry new order-service
cd order-service

# Production bağımlılıkları
poetry add fastapi uvicorn sqlalchemy alembic asyncpg redis celery

# Development araçları
poetry add --group dev pytest pytest-asyncio httpx black ruff mypy

# Staging ve load test araçları
poetry add --group staging locust faker

# Dokümantasyon araçları
poetry add --group docs mkdocs mkdocs-material

# Sadece production bağımlılıklarını kur (CI/CD veya production)
poetry install --only main

# Dev dahil her şeyi kur (local geliştirme)
poetry install

# Belirli grupları dahil et
poetry install --with staging

# Belirli grupları hariç tut
poetry install --without docs

Bu yapı sayesinde production Docker imajınıza gereksiz test ve geliştirme araçları girmiyor, imaj boyutunu küçük tutuyorsunuz.

Lock Dosyası ve Determinizm

poetry.lock dosyası projenin en değerli dosyalarından biri. Bu dosyayı kesinlikle git’e commit etmeniz gerekiyor:

# Lock dosyasını güncelle (pyproject.toml değişikliklerini yansıt)
poetry lock

# Lock dosyasını güncellemeden sadece kur
poetry install --frozen

# Lock dosyası uyumluluğunu kontrol et
poetry check

# Bağımlılık ağacını görüntüle
poetry show --tree

# Belirli paketin detaylarını gör
poetry show fastapi

# Güncel olmayan paketleri listele
poetry show --outdated

# Tüm paketleri ve versiyonlarını listele
poetry show

CI/CD pipeline’larınızda poetry install --frozen kullanmak kritik önem taşıyor. Bu komut poetry.lock dosyasında tanımlı tam versiyonları kuruyor ve dosya yoksa veya güncel değilse hata veriyor. Böylece pipeline’da beklenmedik versiyon yükseltmelerinin önüne geçiyorsunuz.

Docker ile Entegrasyon

Poetry’yi Docker ile kullanırken birkaç kritik nokta var. En yaygın yapılan hata sanal ortamı Docker container içinde de oluşturmak. Container zaten izole olduğu için sanal ortama gerek yok:

# Dockerfile için requirements.txt export
poetry export -f requirements.txt --output requirements.txt --without-hashes

# Dev bağımlılıkları hariç export
poetry export -f requirements.txt --only main --output requirements.txt

# Hash değerleriyle export (güvenlik için önerilir)
poetry export -f requirements.txt --output requirements.txt

Örnek çok aşamalı Dockerfile:

# Build aşaması - poetry.lock'tan requirements üret
FROM python:3.11-slim as builder

WORKDIR /app

RUN pip install poetry==1.7.1

COPY pyproject.toml poetry.lock ./

RUN poetry config virtualenvs.create false && 
    poetry install --only main --no-interaction --no-ansi

# Production aşaması - sadece gerekli dosyalar
FROM python:3.11-slim as production

WORKDIR /app

COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
COPY . .

CMD ["uvicorn", "order_service.main:app", "--host", "0.0.0.0", "--port", "8000"]

Bu yaklaşımla builder aşamasında Poetry ve tüm build araçları var, production imajında sadece uygulama kodu ve gerekli Python paketleri bulunuyor.

Çoklu Python Versiyonu ile Çalışma

Farklı Python versiyonlarını test etmeniz gerektiğinde pyenv ile Poetry kombinasyonu çok işe yarıyor:

# pyenv ile farklı Python versiyonlarını kur
pyenv install 3.10.13
pyenv install 3.11.6
pyenv install 3.12.0

# Proje dizininde kullanılacak versiyonu belirle
pyenv local 3.11.6

# Poetry'yi bu versiyonla kullan
poetry env use $(pyenv which python)

# Farklı Python için ayrı ortam oluştur ve test et
poetry env use python3.10
poetry install
poetry run pytest

poetry env use python3.12
poetry install
poetry run pytest

# Tüm ortamları listele
poetry env list

Bu yaklaşım özellikle kütüphane geliştiriyorsanız ve birden fazla Python versiyonunu desteklemeniz gerekiyorsa hayat kurtarıcı oluyor.

Script ve Komut Tanımlama

Poetry, pyproject.toml içinde proje komutlarını tanımlamanıza olanak veriyor:

[tool.poetry.scripts]
order-api = "order_service.main:run"
migrate = "order_service.db.migrations:run_migrations"
seed = "order_service.db.seed:seed_database"

[tool.taskipy.tasks]
test = "pytest tests/ -v"
lint = "ruff check . && mypy ."
format = "black . && ruff check --fix ."
dev = "uvicorn order_service.main:app --reload --port 8000"
# Tanımlı script'leri çalıştır
poetry run order-api
poetry run migrate

# taskipy ile (poetry add --group dev taskipy gerekir)
poetry run task test
poetry run task lint
poetry run task dev

Paket Yayınlama

Bir kütüphane geliştirip PyPI’a yayınlamak istiyorsanız Poetry bu süreci de kolaylaştırıyor:

# PyPI token ayarla
poetry config pypi-token.pypi your-token-here

# Test PyPI için
poetry config repositories.test-pypi https://test.pypi.org/legacy/
poetry config pypi-token.test-pypi your-test-token

# Paketi oluştur (wheel ve sdist)
poetry build

# Test PyPI'a yayınla
poetry publish -r test-pypi

# PyPI'a yayınla
poetry publish

# Build ve publish tek adımda
poetry publish --build

Sorun Giderme

Pratikte karşılaşılan yaygın sorunlar ve çözümleri:

# Cache sorunları için cache temizle
poetry cache clear --all pypi
poetry cache list

# Bağımlılık çözümleme sorununda verbose mod
poetry install -vvv

# Lock dosyası tutarsızlığı
poetry lock --no-update
poetry install

# Sanal ortamı sıfırla
poetry env remove --all
poetry install

# Dependency resolver timeout sorunları için
poetry config installer.max-workers 4

# pip ile yönetilen sistem Python'unu etkilememek için
poetry config virtualenvs.create true --local

# Proje config'ini görüntüle
poetry config --list

# Global config'i görüntüle
poetry config --list --global

Bir başka sık karşılaşılan durum, şirketteki özel (private) PyPI sunucusunu tanımlamak:

# Özel repository ekle
poetry source add --priority=primary company-pypi https://pypi.sirket.com/simple/

# Kimlik bilgilerini kaydet
poetry config http-basic.company-pypi kullanici sifre

# Sadece özel repo'dan kur
poetry add internal-package --source company-pypi

CI/CD Pipeline Örneği

GitHub Actions ile Poetry entegrasyonu:

# .github/workflows/test.yml içeriği (bash script formatında gösterim)

# Python kurulumu
python -m pip install --upgrade pip
pip install poetry

# Cache için poetry config
poetry config virtualenvs.in-project true

# Bağımlılıkları kur (lock dosyasından, değişiklik olmadan)
poetry install --frozen --no-interaction

# Testleri çalıştır
poetry run pytest tests/ --cov=order_service --cov-report=xml

# Linting
poetry run ruff check .
poetry run mypy order_service/

# Build
poetry build

Cache optimizasyonu için .venv dizinini cache’lemek pipeline süresini önemli ölçüde kısaltıyor. poetry.lock dosyasının hash’ini cache key olarak kullanmak, bağımlılıklar değiştiğinde cache’in otomatik bozulmasını sağlıyor.

Sonuç

Poetry, Python ekosistemindeki bağımlılık yönetimi kargaşasına gerçek bir çözüm sunuyor. pyproject.toml standart haline geldikçe ve poetry.lock ile deterministik kurulumlar mümkün oldukça “benim makinemde çalışıyor” problemi tarih oluyor.

Özellikle birden fazla geliştirici olan ekiplerde, CI/CD pipeline’larında ve Docker tabanlı deployment’larda Poetry’nin getirdiği disiplin ve güvenilirlik paha biçilemez. Bağımlılık gruplarıyla farklı ortamlar için farklı paket setleri tanımlayabilmek, özel repository desteği ve paket yayınlama özelliklerinin tek araçta toplanması da ciddi bir avantaj.

Mevcut projelerinizi Poetry’ye geçirmek düşündüğünüzden daha kolay. poetry init ile mevcut requirements.txt dosyalarındaki bağımlılıkları interaktif olarak ekleyebiliyorsunuz. Yeni projelere başlarken ise artık virtualenv ve pip kombinasyonuna dönmek için hiçbir neden kalmıyor.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir