- Son dönemde yapay zeka geliştirme trendi nedeniyle ciddi şekilde Python öğrenmeye ve kullanmaya başladım; artık bu ekosistemden büyük memnuniyet duyuyorum
- Python, geçmişe kıyasla çok daha hızlı ve modern bir dil haline geldi; Cython ile performans artışı gibi hızlı ilerlemeleri doğrudan hissediyorum
- uv, ruff, pytest, Pydantic gibi modern geliştirme araçları ve kütüphaneleri iş akışıma aktif biçimde dahil ederek geliştirme verimliliğini artırıyorum
- Prodüksiyon ortamı ile Jupyter notebook/komut dosyası tabanlı geliştirme arasındaki farkı azaltmak için proje yapısı ve otomasyon yöntemleri de uyguluyorum
- GitHub Actions, Docker vb. kullanarak CI/CD, test ve altyapı yönetimini verimli biçimde kuruyorum
I’m Switching to Python and Actually Liking It özeti
Neden Python’a geçtim
- Yapay zeka merkezli geliştirme ortamlarında Python fiilî standart dil haline gelmiş durumda
- Geçmişte onu yalnızca basit script’ler yazmak için kullanıyordum, ancak son dönemde RAG, ajanlar ve üretken yapay zeka gibi “gerçek dünyada kullanılan uygulamalar” geliştirmek için ciddi biçimde kullanmaya başladım
- Bu süreçte Python ekosisteminin geçmişe göre çok büyük bir evrim geçirdiğini fark ettim
Python’un 3 güçlü yanı
- Zengin kütüphane ve araç ekosistemi: veri işleme, analiz, web ve yapay zeka için güçlü
- Cython vb. sayesinde performans iyileştirmeleri: derleme tabanlı optimizasyon mümkün
- Geliştirilmiş sözdizimi okunabilirliği:
__init__, __new__ gibi eski sözdizimleri gizlenmiş ve daha sezgisel bir sözdizimi sunuluyor
Proje yapısı (monorepo tabanlı)
Başlıca araçlar ve ayarlar
-
uv
- Astral tarafından sunulan modern Python paket yöneticisi ve build aracı
- Bağımlılık yönetimi, sanal ortam oluşturma, proje başlatma gibi işlerin çoğunu hızlıca hallediyor
pyproject.toml temel yapılandırma dosyası; tüm meta veriler ve bağımlılık bilgileri burada birleşiyor
uv init, uv add, uv sync komutlarıyla proje ortamı hızla kurulabiliyor
-
ruff
- Çok hızlı bir Python linter’ı ve kod biçimlendiricisi
isort, flake8, autoflake vb. araçları bir araya getiriyor
ruff check, ruff format ile lint ve otomatik düzeltme yapılabiliyor
- PEP 8 kodlama stili kılavuzunu varsayılan olarak destekliyor
-
ty
- Astral’ın geliştirdiği Python için statik tip denetleyicisi
typing ile birlikte kullanıldığında statik analiz ve erken hata önleme konusunda etkili
- Hâlâ erken geliştirme aşamasında olsa da istikrarlı biçimde kullanılabilecek seviyede
-
pytest
- Birim test ve genişletilebilir test ortamı sağlayan önde gelen Python test framework’ü
- Basit dosya adlandırma kuralı ve tek komutla doğrudan entegrasyon testi yapılabiliyor
- Testleri
test_*.py olarak düzenleyip uv run pytest ile çalıştırmak yeterli
- Kısa sözdizimi ve zengin eklenti ekosistemi sunuyor
-
Pydantic
- Veri doğrulama ve ortam yapılandırması yönetimi kütüphanesi
.env ortam değişkeni tabanlı ayar yükleme ve tip doğrulama sağlıyor
BaseSettings sınıfı ile API anahtarı veya DB URL gibi bilgileri güvenli şekilde yönetebiliyorsunuz
-
MkDocs
- Python projelerinde statik web sitesi ve dokümantasyon üretimini kolayca destekliyor
- Açık kaynak proje tarzında şık bir tasarımı hızlıca uygulamayı mümkün kılıyor
- GitHub Pages entegrasyonu da kolay
-
FastAPI
- Hızlı RESTful API geliştirme framework’ü
- Otomatik doğrulama ve dokümantasyon, yüksek performans ve kolay Pydantic entegrasyonu gibi avantajlar sunuyor
- Starlette ve Pydantic tabanlı yapısıyla yüksek tip güvenliği ve performans sağlıyor
-
Dataclasses
- Python’un standart özelliği olarak veri odaklı sınıfları kolayca tanımlamayı sağlıyor
- Özel metotları otomatik üretmesi sayesinde boilerplate kodu büyük ölçüde azaltıyor
Sürüm kontrolü ve otomasyon
-
GitHub Actions
project-api ve project-ui için ayrı CI pipeline’ları kuruyorum
- Farklı işletim sistemlerinde CI pipeline’ları kurmak için optimize edilmiş workflow’lar sunuyor
- Docker tabanlı test ortamıyla prodüksiyonla aynı ortamda test yapılabiliyor
-
Dependabot
- Bağımlılıkların otomatik güncellenmesini ve güvenlik yamalarının yönetimini otomatikleştiriyor
-
Gitleaks
- Hassas bilgilerin (parola, API anahtarı vb.) sızmasını önleyen bir araç olarak git commit öncesinde güvenlik taraması yapıyor
-
Pre-commit Hooks
- Commit öncesi otomatik lint, biçimlendirme ve güvenlik taraması için kullanılan araçlar
- ruff, gitleaks vb. ile birlikte kullanılarak kod tutarlılığı ve kalitesi korunuyor
Altyapı otomasyonu
-
Make
make test, make infrastructure-up gibi komutlarla tutarlı bir geliştirme iş akışı sağlıyor
- Proje kökünde ve
project-api içinde ayrı ayrı Makefile bulunuyor
-
Docker & Docker Compose
project-api ve project-ui ayrı container’lar olarak çalıştırılıyor
docker compose up --build -d ile tüm uygulama tek satırda ayağa kaldırılabiliyor
Dockerfile içinde uv kurulumu ve FastAPI uygulamasını çalıştırma komutu yer alıyor
Sonuç
- Bu şekilde modern Python geliştirme ortamında verimli ve sağlam bir prodüksiyon iş akışı kurulabiliyor
- Yapay zeka, veri ve web geliştirme gibi farklı alanlarda Python ekosisteminin büyümesi ve araçların gelişmesi sayesinde birçok avantaj elde edilebiliyor
- Monorepo yapısından otomasyon araçlarına, linter ve tip denetleyicilerinden anında test ortamına, dokümantasyondan altyapı orkestrasyonuna kadar tek ve bütünleşik bir geliştirme kültürü oluşturulabiliyor
6 yorum
Python, kütüphane ve framework açısından zengin olsa da paket sürüm yönetiminin iyi olmaması ve çakışmaların sık yaşanması bir dezavantaj.
Geçmişteki Java ile artı ve eksi yönlerin eğilimi benzer
Yazıda da geçen
uvgerçekten müthiş bir araç. Hızlı olmasının yanında sürüm ve bağımlılık yönetimini de tıpkı npm gibi iyi yaptığı için ben deuvye yerleşiyorum.Yine de bugünlerde
uvve poetry sayesinde sürüm yönetimi ve çakışmaların büyük ölçüde çözüldüğünü düşünüyorum.React ve bu tür kısımlara kadar ekosistemi kapsamak için de uygun mu?
React ile doğrudan entegrasyon, diller farklı olduğu için zorlayıcı olabilecek yönler taşıyor; ancak ne istediğinize bağlı olarak mümkün olan kısımlar da var gibi görünüyor.
Kişisel olarak, Python ile frontend geliştirmenin çok fazla yaygınlaşmış bir alan olmadığını düşünüyorum.
Hacker News görüşü
Kodda ortam değişkeni eksik olduğunda "YOUTUBE_API_KEY veya YOUTUBE_CHANNEL_ID yok" diye OR ile mesaj vermek, aslında OR kullanmaya gerek olmayan bir durumda kullanıcıyı gereksiz yere uğraştırıyor. Her bir değeri ayrı ayrı kontrol edip hangisinin eksik olduğunu açıkça söylemek çok daha iyi bir kullanıcı deneyimi sağlar. Geliştirme süresi farkı da neredeyse yok, o yüzden bunu tavsiye ederim
Küçük ayrıntılara kadar inen bir yorum ama bence bu tür durumlar için := operatörü (walrus operatörü) tam uygun. Örneğin
if not (API_KEY := os.getenv("API_KEY")):şeklinde doğrudan kullanılabilir. Şahsen iç araçlardaos.environ["API_KEY"]içindenKeyError'ın doğrudan fırlamasına izin veriyorum. Bunun da yeterince açık olduğunu düşünüyorumHatta daha da ileri gidip, koşulları tek tek kontrol ederek bir tanesi bile eksikse hepsini birden bildirmek çok daha iyi. Bir değişken eksik diye programı çalıştırıp, ardından başka bir değişken hatası görmek zorunda kalma zahmetini azaltır. Duruma göre bazen kaçınılmaz şekilde uğraştırıcı olabilir ama mümkün olduğunca hepsini tek seferde göstermek iyi olur
En iyisi tüm ortam değişkenlerini alıp, eksik olanları tek seferde raporlamak
Boolean bir bayrak kullanıp en sonda yalnızca bir kez
exit(1)yapmak da bir yöntem. Böylece eksik ortam değişkenlerinin hepsini aynı anda gösterebilirsinexit("Missing ...")gibi, mesajı doğrudan yazdırıp kod 1 ile çıkmak da mümkünProje yapısını otomatik oluşturan bir araç arıyorsanız
cookiecuttertavsiye ederim. Sık kullandığım birkaç şablon var: python-lib, click-app, datasette-plugin, llm-plugin. Şöyle kullanılıyor:uvx cookiecutter gh:simonw/python-libRuby ile
bakerdiye bir şey yaptım. baker, şablon repo'sunu kopyalamıyor; onun yerine yapılacaklar listesi gibi görevler üretiyor ve manuel işleri (API key alıp yapılandırmak gibi) otomatik işlerle (uv initgibi) karıştırabiliyor. Markdown sözdizimi içinde Ruby string interpolation ve bash de kullanılabiliyor. YAML tabanlı config'lerden fazlasıyla bıktığım için bunu yaptımSon dönemde öne çıkan araç
Copier. Ayrıntılar için Copier dokümantasyonuna bakınBen yeni proje kurulumunu yapmaktan hoşlanıyorum. Böyle şeyleri özellikle otomatikleştirmek istemiyorum
Aslında bu tarz yapılandırma otomasyon araçları, günümüzde ajan tabanlı LLM geliştirme iş akışlarına da çok uygun bir alan gibi geliyor
"Python çoğu Unix sisteminde varsayılan olarak geldiği için daha insan dostu" değerlendirmesi biraz fazla iyimser.
import jsonseviyesini geçer geçmez çok hızlı şekildevirtualenvcehennemine düşülüyor. Python 3.13.x ortamında Ubuntu 22.04 veya 24.04, Rocky 9 gibi sistemlerde çalıştırmak istiyorsanız sonundavenv, konteyner veya sürüm yöneticisi zaten zorunlu hale geliyorimport jsongibi temel bir standart kütüphane bile, o dil sisteme dahil değilse ayrıca kurulmak zorunda kalır; Python ise standart kütüphanesi sayesinde başlangıçta yüksek üretkenlik sağlıyor. Elbette büyük projelerde standart kütüphane tek başına yetmez ama pratikte yalnızca standart kütüphane ile birçok gerçek üretim kodu dağıttım ve dağıtım ya da güvenlik yönetimi sorunu yaşamadım.venvyönetimi de eskisi kadar zor değil, paket yöneticileri de geliştiYarı şaka bir teorim şu: Docker/konteynerlerin bu kadar hızlı yayılmasının yarı sebebi, Python bağımlılık cehennemini aşmayı kolaylaştırmış olmaları. Python'la ilk deneyimim 2012'de sunucuya bir Python servisi kurmaktı; bağımlılık cehennemi,
venvkomutları, uğraştırıcı ortam kurulumu, gerçekten korkunçtu.pip,brew, macOS ortamında da sürekli boğuştum ve Python gördüğüm yerde kaçıyordum. Ama son dönemdeuvsayesinde, yeni başlayan biri açısından bile Python çok daha iyi hissettiriyor.uv init,uv add,uv runçoğu zaman yeterliBence
virtualenvher zaman kullanılmalı. Sonuçta sadece bir dizin ve artıkpipile sistem geneline kurulum yapmaya çalışınca uyarılar da çıkıyor; yani eskisi kadar zor değilvirtualenvya da container kullanmak kesinlikle iyi fikir. Zor görünse bile güncellemelerin veya kütüphane sürüm artışlarının tüm sistemi etkilemesini önlüyorEskiden sistemlerde çoğu zaman varsayılan olarak yalnızca Python2 bulunurdu ve bazen sistemin kendisi de bu Python2'ye bağlı olurdu; bu da aslında daha riskliydi
Python bana aynı anda hem fazla ayrıntılı hem de yetersiz geliyor. Basit bir şey yapmak için ya 500 bağımlılık eklemek gerekiyor ya da çok küçük işler için bile kod onlarca, bazen yüzlerce satıra çıkıyor. Bu yüzden Python'da gereksiz sürtünme çok fazla ve ben de kaçınıyorum. Perl ile çok daha hızlı ve öz biçimde bitirebildiğim için Perl'i tercih ediyorum. Python bazen işi yapmak için değil, programlama yapmak için programlama gibi hissettiriyor
Ben bağımlılığı olmayan çok proje yapıyorum. Standart kütüphane ve tek dosyayla gerçekten çok şey yapılabiliyor. Makinede Python kuruluysa
curlile indirip doğrudan çalıştırmak mümkün. Mesela 2000 satırlık bir kişisel finans CLI aracım var: plutus. Yalnızca yaklaşık 12 standart modül kullanıyor. Kodun yaklaşık %25'iargparseile komut ayrıştırma kısmı. Her parametre için bir satır yazma yaklaşımını seviyorum; bence bu daha açıkPerl'in Python'dan daha hızlı ve güçlü olduğunu söyledin; elinde somut örnekler var mı, merak ettim
Python'da veri yapılarını iç içe koyarken fazla düşünmeden ilerleyebilmek rahat. Liste içinde tuple, sözlük vb. serbestçe karıştırılabiliyor ve hepsine tutarlı bir sözdizimiyle erişilebiliyor. Perl kesinlikle daha zeki ve daha eğlenceli ama tam da bu yüzden kafayı daha kolay karıştırabiliyor; en azından benim için öyle. Python biraz sıkıcı ama 5 yıl sonra dönüp baktığımda bile anlayabileceğim kadar açık
Bence Python standart kütüphanesiyle bile gayet kullanılabilir
Ben monorepo yapısını sevenlerdenim ama eski şirketlerimden birinde bu yaklaşım yüzünden devasa ve hantallaşmış bir yapı oluştu; insanlar başka takımın koduna yanlışlıkla dokunmaktan korktukları için neredeyse kimse bir şeye el sürmüyordu. Sorunun özü repo'nun kendisi değil;
requirements.txtdosyasının tüm repo için tek olması veya build script'lerinin dolaşmasıydı. Teoride bağımlılıkları bir kez güncelleyince tüm kodun en son yamalarla güvenli hale gelmesi gerekir ama pratikte kimse bunu yapmaya cesaret edemedi. Monorepo, ancak organizasyon çok güçlü biçimde NIH eğilimliyse (Google gibi her şeyi kendi yapan yapılarda) iyi işliyor. Bu deneyim yüzünden, her servisin organizasyondaki takım yapısıyla hizalandığı mikroservis mimarisine daha çok değer vermeye başladım. Conway yasasına da bakılabilirPython, yazdığım sözde koda en yakın çalışan dil. Zihnimde "bu kısım zaten açık" diye geçtiğim yerlerde Python gerçekten sezgisel soyutlamalar sunuyor. Matematik kökenli bir geçmişten geldiğim için bu bana çok tatmin edici gelmişti. Tabii şimdi başka dilleri de seviyorum ama hâlâ ayrı bir çekiciliği var
Neredeyse tamamen aynı kalıpla proje yapısı kuruyorum. O kadar benziyor ki ürkütücü. Python geliştirici ekosisteminin giderek benzer bir stile yakınsadığını düşünmeye başladım. Eskiden kendi seçimlerimin özgün olduğunu sanıyordum ama herkesin aynı yolu izlemesi, "benim özgür iradem nereye gitti" hissi yaratıyor. Biraz da yaygın bebek ismi seçme durumuna benziyor; benzersiz sandığın tercih aslında en popüler ikinci seçenek çıkıyor
Bu tür yapı Python dünyasında 10 yıldır popüler. Sonuçta birçok makul mühendis düşünüp taşınıp doğal olarak aynı desene geliyor gibi görünüyor
İnsan egosu sanki bir pilot dalga kuantum dalgası gibi tüm spektruma yayılıyor da oradan varlığa dönüşüyor hissi veriyor. becoming-being, insanın gülesi geliyor
Başkalarının da Python'ı sevmeye başlamasını görmek hoşuma gidiyor. Ben aslında Ruby'yi tercih ederdim ama müşteri talepleri yüzünden mecburen Python kullanmaya başladım. Eskiden Ruby çok yavaştı ama istemeden Python öğrenirken giderek alıştım; şimdi bir ölçüde keyif de alıyorum.
Makekullanımı konusunda biraz farklı düşünüyorum; hiç bağımlılık yoksa aslındacasedeyimi içeren bir script'ten çok da farklı değil... Yarı şaka söylüyorum ama yeni neslinMake'e alışık olmaması biraz hüzün veriyor. Tam bir "bizim zamanımızda" duygusuRuby'nin sözdizimi çok daha güzel. Kapsamı sadece girintiyle ayıran Python benim tarzım değil
Ben de önce
casedeyimli bir script'le başlamıştım, sonra düz birMakefile'a evrildi.Makefiledaha standart ve rastgele bir script'ten daha okunaklıDataclass ile Pydantic Basemodel arasında hangisinin kullanılması gerektiğini merak ediyorum. Zaten Pydantic kullanıyorsanız her şeyi Pydantic ile birleştirmek daha mantıklı olmaz mı diye düşünüyorum; ayrıca Dataclass kullanmak için gerçekten bir sebep var mı emin değilim
attrs projesinin bunu çok iyi toparlayan bir karşılaştırma yazısı var. attrs resmi karşılaştırması burada; tabii biraz taraflı olabilir ama mantıksal dayanakları yeterince güçlü. Ayrıca bu blog yazısı da yardımcı olabilir
Dataclass, iç içe geçmiş nesne doğrulamasını desteklemiyor. Bu yüzden sadece fonksiyon argümanlarını aktarmak için kullanılan düz yapılarda dataclass daha uygun. Çok fazla argümanı liste gibi geçirmekten daha açık oluyor
Oluşturma sırasında veri doğrulaması nedeniyle performans kaybı sorunu var.
msgspecgibi çok daha hafif ve hızlı alternatifler de mevcutDoğrulama veya serileştirme gerekmiyorsa Pydantic aslında gereksiz ek yük. Benim kuralım şu: serileştirme gerekiyorsa Pydantic, gerekmiyorsa dataclass
TypeAdapter(MyDataclass)gibi mevcut dataclass'ı doğrudan kullanabiliyorken ayrıca Pydantic modeli oluşturmaya gerçekten gerek var mı emin değilimSon dönemde aslında Python'dan değil, başka dillere geçince daha memnun oldum. Python hakkındaki düşüncelerimi şu yazıda topladım. Bir gün tekrar Python kullanmam gerekirse
uv,ruff,tygibi araçları mutlaka denerimasyncoldu. Python'daasynciovar ama birden fazla rakip yaklaşım olduğu için ortada net bir standart yok. JS'de her şeyin tek bir yaklaşıma oturmuş olması işi çok kolaylaştırdı. Küçük ayrıntılar da üst üste eklenince büyük fark yaratıyor; Python'da girintiyle scope belirlenmesi, import'larda göreli yol sorunları, JS nesne sözdizimi gibi konularda JS bana daha rahat geldi. İlgili açıklama burada