Asenkron Programlama
Hoşgeldiniz. Direkt ayakkabılarla girebilirsiniz buyurun.
Yazılım hayatınızın bir parçasıysa, mutlaka “asenkron” kelimesini duymuşsunuzdur. “Abi bu ekran niye donuyor ya!” veya “Neden kasıyor bu uygulama?” gibi yakınmalar da belki size tanıdık geliyordur. Async, task, await, event loop gibi terimler de gözünüze çarpmış olabilir. Bu saydıklarım asenkron programlamayla ilgilidir. Bu yazımda ise görece kompleks veya zor olarak düşünülen bu konu hakkında temel seviyeden başlayarak, profesyonel hayattaki kullanımına kadar asenkron programlamayı anlatmaya çalışacağım. Umarım faydalı olur ve okurken keyif alırsınız.
Asenkron programlamanın ne olduğunu, nasıl yapıldığını, neden ihtiyaç duyduğumuzu, neden yapıldığı vesaire bunlara girişmeden önce asenkron kelimesinin anlamına bakalım.
Asenkron: başlama ve sona erme zamanları ayrı olan, aynı zamanda olmayan (olgular, olaylar).
Pekala, farklı zamanlarda başlayıp farklı zamanlarda biten olaylarımız var. Belli ki bu olayların başlangıç ve bitiş zamanları birbirlerini etkilemiyor. Bunu biraz da görselleştirelim hadi.
Burada “olaylar” diye bahsettiğimiz ve şekilde renkli barlarla temsil edilen şeyleri, temizlik gününde yapılacak olan işlerin olduğunu varsayalım. Todo listemiz evin toparlanması, süpürülmesi, paspas atılması, çamaşır ve bulaşıkların yıkanmasından oluşsun.
Çamaşır ve bulaşıkları makine ile yıkanacağını varsayarsak bugünün planını nasıl yapardınız? Çamaşır ve bulaşıkları makineye attıktan sonra hemen ortalığı toparlar, süpürge ve vileda ile günün bitirirdiniz değil mi?Önden çamaşır ve bulaşık makinesini başlattık ki, biz ortalığı temizlerken onlar arka planda çalışsın. Çünkü makinelerin çalışması, evin süpürülmesini etkileyen bir süreç değil. Ama paspas atmadan önce evi toparlayıp, süpürmem gerekir, çünkü bu “olaylar” birbirinin sonuçlarını etkileyecektir.
Evet, zaten bildiğiniz şeyleri size tekrar söyleyerek aslında asenkron çalışan fonksiyonları kafanızda canlanmasını istedim. Biz standart programlamada, asenkron fonksiyonlar kullanmazsak, “bu arka planda çalışadursun, ben şunu halledeyim” gibi bir şey söyleyemeyiz. Yukarıdan aşağıya doğru bir satır derlenmeden bir diğerine geçemeyiz.
Şimdi, programlama dünyasına dönecek olursak, asenkron işlemlerin sıklıkla kullanıldığı birkaç senaryoya bakalım:
- Ağ Operasyonları: Bir uygulama, bir web sunucusuna veya bir veritabanına bağlanıp veri çekerken beklemek zorunda kalabilir. Eğer bu işlem asenkron yapılmazsa, kullanıcı arayüzü donabilir veya tüm programın işleyişi durabilir.
- Dosya İşlemleri: Diskten büyük bir dosya okurken programın diğer işlemlerine devam etmesini isteyebiliriz. Dosya okumayı asenkron yaparak bu mümkün olur.
- Kullanıcı Arayüzü: Masaüstü veya mobil uygulamalarda, kullanıcı etkileşimleriyle ilgili işlemler genellikle asenkron yapılır. Bir düğmeye tıklandığında, uzun sürecek bir işlem başlatıldığında kullanıcı arayüzü donmamalıdır.
Peki, nasıl yapıyoruz?
import asyncio
async def yemek_yap():
print("Makarnayı suya koyuyorum.")
await asyncio.sleep(5)
print("Makarna hazır!")
async def masa_hazirla():
print("Masayı kuruyorum.")
await asyncio.sleep(2)
print("Masa hazır!")
async def ana_program():
await asyncio.gather(
yemek_yap(),
masa_hazirla()
)
asyncio.run(ana_program())
Bu kodda iki işlem aynı anda çalışıyor gibi görünüyor. Ancak, aslında arka planda bir olay döngüsü (event loop) işlemleri sıraya koyarak, zamanı verimli kullanıyor. İlk işlem beklerken, diğeri çalışıyor.
Diyelim ki bir dosya indirme uygulaması yazıyorsunuz ve aynı anda birden fazla dosyayı indirmeniz gerekiyor. Eğer bu işlemi senkron yaparsanız, her indirme işlemi sırayla tamamlanacak ve kullanıcı çok uzun süre bekleyecektir. Ancak, asenkron bir yapı ile bu süreci hızlandırabilirsiniz.
import asyncio
async def dosya_indir(dosya_adi, bekleme_suresi):
print(f"{dosya_adi} indirilmeye başlandı.")
await asyncio.sleep(bekleme_suresi)
print(f"{dosya_adi} indirildi.")
async def ana_program():
await asyncio.gather(
dosya_indir("Dosya1.zip", 3),
dosya_indir("Dosya2.zip", 5),
dosya_indir("Dosya3.zip", 2),
)
asyncio.run(ana_program())
Bu kod çalıştığında, indirme işlemleri birbirini beklemek yerine paralel bir şekilde gerçekleşir. İlk indirme işlemi beklerken diğer indirme işlemleri başlar. Bu, asenkron programlamanın gücünü bir kez daha gösteriyor.
Günümüzde uygulamaların çoğu, API’lere veri gönderip alıyor. Örneğin, bir hava durumu uygulamasını düşünün. Aynı anda birden fazla şehir için hava durumunu kontrol etmek isteyebilirsiniz. Asenkron programlama burada da hayat kurtarıcıdır.
import asyncio
import random
async def hava_durumu_sorgula(sehir):
print(f"{sehir} için hava durumu sorgulanıyor...")
await asyncio.sleep(random.randint(1, 3)) # Farklı sürelerde gecikme simülasyonu
print(f"{sehir} için hava durumu geldi!")
async def ana_program():
sehirler = ["İstanbul", "Ankara", "İzmir", "Bursa", "Antalya"]
await asyncio.gather(*(hava_durumu_sorgula(sehir) for sehir in sehirler))
asyncio.run(ana_program())
Bu örnekte, her şehir için hava durumu sorgulama işlemi birbirini beklemeden gerçekleşir. Sonuç olarak, tüm sorgulamalar daha kısa sürede tamamlanır.
Bir masaüstü uygulamasında, kullanıcı bir butona bastığında bir işlem başlattığınızı düşünün. Eğer işlem uzun sürerse ve senkron çalışıyorsanız, arayüz donabilir. Ancak, asenkron bir yapı ile kullanıcıya bu sürede hâlâ diğer işlevlere erişim imkanı sunabilirsiniz.
Python için popüler bir GUI kütüphanesi olan tkinter
ile asenkron bir örnek:
import asyncio
import tkinter as tk
async def uzun_islem():
await asyncio.sleep(5)
print("Uzun işlem tamamlandı!")
def uzun_islem_baslat():
asyncio.create_task(uzun_islem())
print("Uzun işlem başlatıldı, kullanıcı arayüzü donmuyor!")
root = tk.Tk()
root.title("Asenkron GUI Örneği")
btn = tk.Button(root, text="Uzun İşlem Başlat", command=uzun_islem_baslat)
btn.pack()
root.mainloop()
Burada asyncio.create_task
kullanarak arka planda uzun bir işlem başlatıyoruz. Kullanıcı arayüzü donmadan işlem devam eder.
Asenkron Programlama ile Senkron Programlama Arasındaki Farklar
Senkron programlamada bir işlem tamamlanmadan diğerine geçilmez. Bu, küçük işlemlerde sorun yaratmazken, büyük veri işlemlerinde veya uzun süren işlemlerde programın tamamen bloke olmasına neden olabilir. Asenkron programlama ise bu tür sorunları çözmek için harika bir araçtır. “Bir işlemi beklerken, diğer işlemleri halledebilmek” asenkronluğun temel avantajıdır.
Gerçek Hayatta Kullanımı
Asenkron programlama, özellikle web uygulamaları ve mikro servis tabanlı sistemlerde oldukça yaygındır. Örneğin, bir e-ticaret sitesinde ödeme işlemi yapılırken kullanıcıya “işlem sürüyor” mesajı gösterilir. Arkada ödeme onaylanırken kullanıcı başka şeyler yapabilir.
Bu yazımın da sonuna geldim. Okuduğunuz için teşekkür ederim.
Unutmayın ki, good things come to those who code..