ProgrammatieBackend ontwikkelaar

Leg uit hoe asynchroon programmeren in Python wordt geïmplementeerd met behulp van async/await. Wat zijn de voordelen en uitdagingen van deze benadering?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Asynchroon programmeren is geïntroduceerd in Python vanaf versie 3.5 met de invoering van de sleutelwoorden async en await. Eerst werden asynchrone taken uitgevoerd met behulp van bibliotheken zoals asyncio en generatoren op basis van coroutines, wat moeilijk te begrijpen en onderhouden was. Met de komst van de syntaxis async/await is de asynchrone code duidelijker en leesbaarder geworden, meer in lijn met de gebruikelijke synchrone stijl.

Historisch aspect

Voor de komst van async/await werd asynchroniciteit gerealiseerd via callbacks en generatoren (bijvoorbeeld met de bibliotheek tornado of oude API's van asyncio). Deze code was moeilijk te debuggen en te onderhouden.

Probleem

Het grootste probleem bij het verwerken van een groot aantal gelijktijdige I/O-bewerkingen (netwerkverzoeken, bestandsinvoer/uitvoer) in synchrone code is de blokkering van de hoofdthread. Dit leidt tot verminderde prestaties en onmogelijk gebruik van middelen op een effectieve manier.

Oplossing

Asynchroon programmeren met behulp van async/await maakt het mogelijk om meerdere invoer-/uitvoeroperaties parallel uit te voeren binnen één thread, waardoor blokkeringen worden vermeden. De syntaxis is bovendien dichtbij de gebruikelijke functies, wat de leesbaarheid en het debuggen vergemakkelijkt.

Voorbeeldcode:

import asyncio async def fetch_data(delay): print(f"Start ophalen na {delay}s vertraging") await asyncio.sleep(delay) print(f"Klaar met ophalen na {delay}s vertraging") return delay async def main(): results = await asyncio.gather( fetch_data(1), fetch_data(2), fetch_data(3) ) print("Resultaten:", results) asyncio.run(main())

Sleutelkenmerken:

  • Geen blokkering van de thread: invoer-/uitvoeroperaties ontgrendelen de thread.
  • Duidelijke syntaxis (async/await) voor asynchrone aanroepen.
  • Eenvoudige integratie met bibliotheken die asyncio ondersteunen.

Vragen met een strikvraag.

Kan een functie, gedefinieerd met behulp van async def, worden aangeroepen als een gewone functie?

Nee. Het aanroepen van zo'n functie retourneert een coroutine-object dat niet wordt uitgevoerd totdat het aan de event loop wordt doorgegeven (bijvoorbeeld met behulp van await of asyncio.run()).

def foo(): return 42 async def bar(): return 42 print(foo()) # 42 print(bar()) # <coroutine object bar at ...>

Kan await buiten een asynchrone functie worden gebruikt?

Nee. Het sleutelwoord await moet alleen binnen functies worden gebruikt die zijn gedefinieerd met async def. Poging om await buiten zo'n functie te plaatsen zal een SyntaxError opleveren.

# Fout! await asyncio.sleep(1) # SyntaxError: 'await' buiten asynchrone functie

Werkt asynchroniciteit voor operaties die niet met I/O te maken hebben (bijvoorbeeld berekeningen)?

Nee. Asynchroniciteit is alleen effectief voor invoer-/uitvoeroperaties. Voor rekentaken zijn nog steeds multiprocessing of threading nodig, anders wordt de event loop geblokkeerd.

Typische fouten en anti-patronen

Voordelen:

  • Vermindert aanzienlijk de wachttijd voor I/O-operaties.
  • Verhoogt de reactietijd van servers en applicaties.
  • Behoudt de enkelvoudige aard van de code en omzeilt problemen met multithreading.

Nadelen:

  • Asynchrone code is moeilijk te testen.
  • Er is ondersteuning voor asynchroniciteit van bibliotheken nodig (niet alle ondersteunen asyncio).
  • Misverstand dat asynchroniciteit berekeningen versnelt — dit is alleen waar voor I/O.

Voorbeeld uit het leven

Negatieve case: Jonge ontwikkelaars besloten een applicatie te versnellen met async/await, maar maakten de asynchrone berekeningen, niet de netwerkverzoeken. De applicatie werd niet sneller. Voordelen: maakten kennis met de syntaxis. Nadelen: geen winst, de code werd complexer.

Positieve case: Verwerkten asynchroon duizenden verzoeken naar de API. De server kon meer klanten bedienen zonder extra middelen te verhogen. Voordelen: de prestaties namen aanzienlijk toe, de architectuur werd eenvoudiger. Nadelen: de instapdrempel voor beginners steeg.