MC, 2025
Ilustracja do artykułu: Python asyncio – Jak wykorzystać asynchroniczność w Pythonie? Przykłady i wskazówki

Python asyncio – Jak wykorzystać asynchroniczność w Pythonie? Przykłady i wskazówki

W świecie programowania asynchroniczność to temat, który staje się coraz bardziej popularny, zwłaszcza w kontekście aplikacji wymagających dużej liczby operacji we/wy. Python, jako jeden z najczęściej wybieranych języków, posiada wyjątkowo dobrze rozwiniętą bibliotekę do pracy z asynchronicznością – asyncio. Dziś opowiemy o tym, czym jest python asyncio, jak go wykorzystać i pokażemy kilka praktycznych przykładów, które pomogą Ci zrozumieć, jak poprawić wydajność Twoich aplikacji.

Co to jest Python asyncio?

asyncio to biblioteka w Pythonie, która pozwala na pisanie kodu asynchronicznego przy użyciu tzw. "coroutines" (funkcje, które mogą być wstrzymywane i wznawiane). Dzięki niej możemy wykonywać operacje równolegle, bez blokowania głównego wątku programu. Co więcej, asyncio jest idealne do aplikacji, które wymagają pracy z siecią, bazami danych, a także przy rozwiązywaniu problemów związanych z długotrwałymi zadaniami, które mogłyby spowolnić program, gdyby były wykonywane synchronicznie.

Dlaczego warto używać Python asyncio?

Praca z asynchronicznością jest szczególnie korzystna w przypadkach, gdy mamy do czynienia z wieloma zadaniami we/wy, takimi jak pobieranie danych z serwera, odczytywanie plików czy zapisywanie danych do bazy. W tradycyjnym, synchronicznym podejściu takie operacje blokowałyby działanie programu, co prowadziłoby do opóźnień. Dzięki asyncio, możemy jednocześnie obsługiwać wiele zadań, co przyspiesza działanie aplikacji.

Jak działa Python asyncio?

W asyncio kluczowym elementem są tzw. "coroutines" (korutyny). To funkcje, które zawierają słowo kluczowe async i są zaprojektowane w taki sposób, że mogą być wstrzymywane w jednym momencie i wznowione w innym. Zamiast czekać na zakończenie jednej operacji, aplikacja może przejść do następnej, co pozwala na równoczesne wykonywanie wielu zadań.

W asyncio używamy specjalnej pętli, tzw. "event loop", która zarządza wykonywaniem tych asynchronicznych operacji. W ten sposób, zamiast blokować program na czas oczekiwania, możemy wykonać inne zadania w tle. To znacząco poprawia wydajność.

Podstawowe elementy asyncio

Przed przystąpieniem do pracy z asyncio, warto poznać kilka podstawowych elementów tej biblioteki:

  • Coroutines – Funkcje zdefiniowane przy użyciu słowa kluczowego async, które można wstrzymywać i wznawiać przy pomocy await.
  • await – Słowo kluczowe, które pozwala na wstrzymanie wykonania coroutine do czasu zakończenia operacji.
  • event loop – Pętla zdarzeń, która odpowiada za uruchamianie i zarządzanie coroutine oraz zadaniami asynchronicznymi.
  • asyncio.run() – Funkcja, która uruchamia nasz kod w kontekście event loopa i zarządza jego zakończeniem.

Przykład podstawowego użycia Python asyncio

Oto najprostszy przykład wykorzystania asyncio w Pythonie. W tym przykładzie stworzymy dwie funkcje, które będą symulowały opóźnienia i będą działały asynchronicznie:

import asyncio

# Definicja funkcji asynchronicznej
async def hello_world():
    print("Rozpoczynamy!")
    await asyncio.sleep(2)  # Symulacja opóźnienia
    print("Cześć, świat!")

# Uruchomienie pętli zdarzeń
asyncio.run(hello_world())

W tym przykładzie funkcja hello_world jest coroutine, która najpierw wypisuje "Rozpoczynamy!", a potem czeka 2 sekundy (symulując opóźnienie) przy pomocy await asyncio.sleep(2). Następnie wypisuje "Cześć, świat!". Co ważne, podczas oczekiwania na zakończenie funkcji sleep, program nie jest blokowany i mógłby wykonać inne operacje.

Przykład z wieloma zadaniami

Teraz, gdy znamy podstawy, przyjrzymy się, jak możemy wykonać kilka zadań asynchronicznie w tym samym czasie. Oto przykład, który uruchamia kilka asynchronicznych funkcji równocześnie:

import asyncio

# Definicja dwóch funkcji asynchronicznych
async def task_1():
    print("Rozpoczynam task 1")
    await asyncio.sleep(1)
    print("Zakończono task 1")

async def task_2():
    print("Rozpoczynam task 2")
    await asyncio.sleep(2)
    print("Zakończono task 2")

# Uruchamianie dwóch zadań jednocześnie
async def main():
    await asyncio.gather(task_1(), task_2())

# Uruchomienie event loopa
asyncio.run(main())

W tym przykładzie mamy dwie asynchroniczne funkcje task_1 i task_2, które symulują opóźnienia o różnych czasach. Zamiast wykonywać je po kolei, używamy asyncio.gather(), aby uruchomić je równolegle. Dzięki temu czas oczekiwania na zakończenie obu zadań wynosi tylko 2 sekundy, zamiast 3, jak miałoby to miejsce w przypadku tradycyjnego podejścia synchronicznego.

Zaawansowane przykłady w Python asyncio

Python asyncio oferuje także bardziej zaawansowane mechanizmy, które pomagają w zarządzaniu wieloma zadaniami. Oto kilka z nich:

  • asyncio.Queue – Kolejka, która pozwala na wymianę danych pomiędzy zadaniami asynchronicznymi.
  • asyncio.create_task() – Funkcja, która tworzy zadanie w tle, pozwalając na równoczesne uruchamianie wielu funkcji asynchronicznych.
  • asyncio.Event – Obiekt synchronizacji, który pozwala na kontrolowanie kolejności wykonywania zadań.

Przykład z asyncio.Queue

W przypadku, gdy chcemy przekazać dane między różnymi zadaniami, pomocna może być asyncio.Queue. Oto przykład, w którym dwa zadania asynchroniczne wymieniają się danymi:

import asyncio

async def producer(queue):
    for i in range(5):
        await asyncio.sleep(1)
        await queue.put(i)
        print(f"Producent dodał {i}")

async def consumer(queue):
    while True:
        item = await queue.get()
        if item is None:
            break
        print(f"Konsument odebrał {item}")

async def main():
    queue = asyncio.Queue()
    await asyncio.gather(producer(queue), consumer(queue))

asyncio.run(main())

W tym przykładzie mamy funkcję producer, która dodaje liczby do kolejki, oraz funkcję consumer, która te liczby odbiera. Dzięki temu rozwiązaniu, zadania mogą wymieniać się danymi w sposób asynchroniczny i efektywny.

Podsumowanie

Python asyncio to potężne narzędzie, które pozwala na zarządzanie asynchronicznymi operacjami w sposób prosty i efektywny. Dzięki wykorzystaniu coroutine, event loopa i funkcji takich jak asyncio.gather() czy asyncio.Queue, możemy tworzyć aplikacje, które są szybsze, bardziej skalowalne i bardziej responsywne. Choć początkowo może to wydawać się skomplikowane, po kilku próbach szybko zrozumiesz, jak duże korzyści płyną z asynchroniczności w Pythonie.

Komentarze (1)

Imię:
Treść:
Tomasz 2026-05-05 14:47:50
Ten ostatni przykład wymaga siłowego zakończenia. Po zakończeniu pętli producent powinien wysłać na koniec do kolejki obiekt None aby konsument nie musiał czekać w nieskończoność.