1. Asenkron Fonksiyonlar ile Çalışırken `await` Kullanmayı Unutmak
Python'da asenkron fonksiyonlar oluşturduğunda, bu fonksiyonların çalışması beklenmedik bir hızda olabilir. Ancak, bu fonksiyonları çağırırken `await` kullanmayı unutmamalısınız. Aksi takdirde, programınızın asenkron doğası kaybolur ve işler sıralı bir şekilde çalışmaya başlar.
import asyncio
async def fetch_data():
await asyncio.sleep(1)
return "Data fetched!"
async def main():
result = fetch_data() # await eksik
print(result)
asyncio.run(main())
```
Yukarıdaki örnekte, `fetch_data()` fonksiyonu asenkron bir fonksiyon olmasına rağmen, `await` kullanılmadığı için hemen bir değer döndürür. Bu hatayı düzeltmek için `await` anahtar kelimesini kullanmalısınız:
```python
async def main():
result = await fetch_data() # await eklenmiş
print(result)
```
2. `asyncio.run()` Fonksiyonunu Yanlış Kullanın
Birçok Python geliştiricisi, `asyncio.run()` fonksiyonunun ne zaman ve nasıl kullanılacağını öğrenmekte zorlanır. `asyncio.run()`, yalnızca bir kere çalıştırılmalıdır ve programın ana asenkron işlevini başlatmak için kullanılır.
```python
async def task():
await asyncio.sleep(1)
print("Task complete!")
asyncio.run(task())
asyncio.run(task()) # Burada hata oluşur!
```
Bu hatayı çözmek için sadece bir defa `asyncio.run()` fonksiyonu çağrılmalıdır.
3. Birden Fazla Asenkron Görev Arasında Senkronizasyon Sorunları
Asenkron görevler arasında senkronizasyon yapmak karmaşık olabilir. Bu, özellikle veritabanı işlemleri veya dosya okuma/yazma gibi I/O işlemleri sırasında yaşanır. `asyncio.gather()` fonksiyonu, birden fazla asenkron görevi aynı anda çalıştırmanıza olanak tanır. Ancak, görevler arasındaki senkronizasyonu sağlamak önemlidir.
async def task_1():
await asyncio.sleep(1)
print("Task 1 completed!")
async def task_2():
await asyncio.sleep(2)
print("Task 2 completed!")
async def main():
await asyncio.gather(task_1(), task_2())
asyncio.run(main())
```
Bu örnekte, `asyncio.gather()` kullanarak her iki görevi de paralel olarak çalıştırıyoruz. Sonuçta Task 1 ve Task 2 tamamlandığında her iki görev de düzgün bir şekilde tamamlanmış olur.
4. Zaman Aşımını Yönetmeyi Unutmak
Asenkron programlamada zaman aşımı yönetimi de önemlidir. Uygulamanızın belirli bir süre içinde cevap alması gereken durumlar olabilir. `asyncio.wait_for()` fonksiyonu, zaman aşımı sürelerini yönetmenize yardımcı olur.
async def fetch_data_with_timeout():
await asyncio.sleep(2)
return "Data fetched!"
async def main():
try:
result = await asyncio.wait_for(fetch_data_with_timeout(), timeout=1)
print(result)
except asyncio.TimeoutError:
print("Task timed out!")
asyncio.run(main())
```
Bu kod, `fetch_data_with_timeout()` fonksiyonunun 1 saniye içinde tamamlanmasını bekler. Eğer bu süre aşılırsa, bir `TimeoutError` hatası fırlatılır.
5. Asenkron Kodda `try-except` Bloklarını Kullanmayı Unutmak
Asenkron programlamada hataların düzgün bir şekilde yönetilmesi çok önemlidir. `try-except` blokları, hata yönetimini düzgün bir şekilde yapmanıza olanak tanır. Asenkron fonksiyonlarda bu blokları kullanmak, beklenmedik hatalarla karşılaştığınızda uygulamanızın çökmesini engeller.
async def risky_task():
raise ValueError("Something went wrong!")
async def main():
try:
await risky_task()
except ValueError as e:
print(f"Caught error: {e}")
asyncio.run(main())
```
Yukarıdaki örnekte, `risky_task()` fonksiyonu bir hata fırlatıyor ve bu hata `try-except` bloğu ile yakalanıyor.
### Sonuç
Python'da asenkron programlama, güçlü bir araçtır ancak dikkatli kullanılmalıdır. `asyncio` kütüphanesini etkin bir şekilde kullanmak için yukarıda belirtilen yaygın hatalardan kaçınmalısınız. Her zaman doğru `await` kullanımına, zaman aşımı yönetimine ve hata yakalama tekniklerine dikkat etmek, verimli ve güvenilir asenkron uygulamalar geliştirmenizi sağlar.